MatplotLibAPI 3.2.20__tar.gz → 3.2.21__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Bubble.py +3 -2
  2. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Composite.py +98 -5
  3. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Network.py +43 -10
  4. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Table.py +3 -3
  5. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Timeserie.py +3 -2
  6. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Wordcloud.py +9 -12
  7. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/__init__.py +6 -1
  8. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/accessor.py +29 -28
  9. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/PKG-INFO +1 -1
  10. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/pyproject.toml +1 -1
  11. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_wordcloud.py +32 -14
  12. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/.github/workflows/ci.yml +0 -0
  13. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/.github/workflows/python-publish.yml +0 -0
  14. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/.gitignore +0 -0
  15. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/AGENTS.md +0 -0
  16. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/LICENSE +0 -0
  17. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Area.py +0 -0
  18. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Bar.py +0 -0
  19. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/BoxViolin.py +0 -0
  20. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Heatmap.py +0 -0
  21. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Histogram.py +0 -0
  22. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Pie.py +0 -0
  23. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Pivot.py +0 -0
  24. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Sankey.py +0 -0
  25. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/StyleTemplate.py +0 -0
  26. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Sunburst.py +0 -0
  27. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Treemap.py +0 -0
  28. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/Waffle.py +0 -0
  29. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/_typing.py +0 -0
  30. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/MatplotLibAPI/_visualization_utils.py +0 -0
  31. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/README.md +0 -0
  32. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/SECURITY.md +0 -0
  33. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/SUGGESTIONS.md +0 -0
  34. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/scripts/generate_sample_data.py +0 -0
  35. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/__init__.py +0 -0
  36. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/conftest.py +0 -0
  37. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_area.py +0 -0
  38. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_bar.py +0 -0
  39. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_box_violin.py +0 -0
  40. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_bubble.py +0 -0
  41. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_dependencies.py +0 -0
  42. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_heatmap.py +0 -0
  43. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_histogram.py +0 -0
  44. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_network.py +0 -0
  45. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_pie.py +0 -0
  46. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_pivot.py +0 -0
  47. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_sankey.py +0 -0
  48. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_smoke.py +0 -0
  49. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_sunburst.py +0 -0
  50. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_table.py +0 -0
  51. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_timeseries.py +0 -0
  52. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_treemap.py +0 -0
  53. {matplotlibapi-3.2.20 → matplotlibapi-3.2.21}/tests/test_waffle.py +0 -0
@@ -15,6 +15,7 @@ from matplotlib.ticker import NullLocator
15
15
 
16
16
  from .StyleTemplate import (
17
17
  BUBBLE_STYLE_TEMPLATE,
18
+ FIG_SIZE,
18
19
  MAX_RESULTS,
19
20
  StyleTemplate,
20
21
  bmk_formatter,
@@ -373,7 +374,7 @@ def fplot_bubble(
373
374
  ascending: bool = False,
374
375
  hline: bool = False,
375
376
  vline: bool = False,
376
- figsize: Tuple[float, float] = (19.2, 10.8),
377
+ figsize: Tuple[float, float] = FIG_SIZE,
377
378
  save_path: Optional[str] = None,
378
379
  savefig_kwargs: Optional[Dict[str, Any]] = None,
379
380
  ) -> Figure:
@@ -408,7 +409,7 @@ def fplot_bubble(
408
409
  vline : bool, optional
409
410
  Draw vertical line at mean x. The default is `False`.
410
411
  figsize : tuple[float, float], optional
411
- Size of the figure. The default is (19.2, 10.8).
412
+ Size of the figure. The default is FIG_SIZE.
412
413
 
413
414
  Returns
414
415
  -------
@@ -1,6 +1,6 @@
1
1
  """Composite plotting routines combining multiple charts."""
2
2
 
3
- from typing import Dict, Optional, Tuple, cast
3
+ from typing import Dict, Iterable, Optional, Tuple, cast
4
4
 
5
5
  import matplotlib.pyplot as plt
6
6
  import pandas as pd
@@ -9,10 +9,12 @@ from matplotlib.figure import Figure
9
9
  from matplotlib.gridspec import GridSpec
10
10
  from plotly.subplots import make_subplots
11
11
 
12
- from .Bubble import BUBBLE_STYLE_TEMPLATE, aplot_bubble
13
- from .StyleTemplate import StyleTemplate, validate_dataframe
12
+ from .Bubble import BUBBLE_STYLE_TEMPLATE, FIG_SIZE, aplot_bubble
13
+ from .Network import NETWORK_STYLE_TEMPLATE, aplot_network
14
+ from .StyleTemplate import MAX_RESULTS, StyleTemplate, validate_dataframe
14
15
  from .Table import aplot_table
15
16
  from .Treemap import TREEMAP_STYLE_TEMPLATE, aplot_treemap
17
+ from .Wordcloud import WORDCLOUD_STYLE_TEMPLATE, aplot_wordcloud
16
18
 
17
19
 
18
20
  def plot_composite_bubble(
@@ -29,7 +31,7 @@ def plot_composite_bubble(
29
31
  sort_by: Optional[str] = None,
30
32
  ascending: bool = False,
31
33
  table_rows: int = 10,
32
- figsize: Tuple[float, float] = (19.2, 10.8),
34
+ figsize: Tuple[float, float] = FIG_SIZE,
33
35
  ) -> Figure:
34
36
  """Plot a composite bubble chart with summary tables.
35
37
 
@@ -62,7 +64,7 @@ def plot_composite_bubble(
62
64
  table_rows : int, optional
63
65
  Number of rows to display in the tables. The default is 10.
64
66
  figsize : tuple[float, float], optional
65
- Size of the created figure. The default is (19.2, 10.8).
67
+ Size of the created figure. The default is FIG_SIZE.
66
68
 
67
69
  Returns
68
70
  -------
@@ -193,3 +195,94 @@ def plot_composite_treemap(
193
195
  current_row += 1
194
196
  return fig
195
197
  return None
198
+
199
+
200
+ def plot_wordcloud_network(
201
+ nodes_df: pd.DataFrame,
202
+ edges_df: pd.DataFrame,
203
+ text_column: str = "node",
204
+ node_weight: Optional[str] = "weight",
205
+ source: str = "source",
206
+ target: str = "target",
207
+ edge_weight: str = "weight",
208
+ wordcloud_title: Optional[str] = None,
209
+ network_title: Optional[str] = None,
210
+ wordcloud_style: StyleTemplate = WORDCLOUD_STYLE_TEMPLATE,
211
+ network_style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
212
+ max_words: int = MAX_RESULTS,
213
+ stopwords: Optional[Iterable[str]] = None,
214
+ figsize: Tuple[float, float] = FIG_SIZE,
215
+ ) -> Figure:
216
+ """Plot a word cloud above a network graph.
217
+
218
+ Parameters
219
+ ----------
220
+ nodes_df : pd.DataFrame
221
+ DataFrame containing node labels and optional weights for the word cloud.
222
+ edges_df : pd.DataFrame
223
+ DataFrame containing edge connections for the network plot.
224
+ text_column : str, optional
225
+ Column in ``nodes_df`` containing the node labels. The default is ``"node"``.
226
+ node_weight : str, optional
227
+ Column in ``nodes_df`` containing weights for sizing words. The default is
228
+ ``"weight"``.
229
+ source : str, optional
230
+ Column in ``edges_df`` containing source nodes. The default is ``"source"``.
231
+ target : str, optional
232
+ Column in ``edges_df`` containing target nodes. The default is ``"target"``.
233
+ edge_weight : str, optional
234
+ Column in ``edges_df`` containing edge weights. The default is ``"weight"``.
235
+ wordcloud_title : str, optional
236
+ Title for the word cloud subplot. The default is ``None``.
237
+ network_title : str, optional
238
+ Title for the network subplot. The default is ``None``.
239
+ wordcloud_style : StyleTemplate, optional
240
+ Style configuration for the word cloud. The default is
241
+ ``WORDCLOUD_STYLE_TEMPLATE``.
242
+ network_style : StyleTemplate, optional
243
+ Style configuration for the network graph. The default is
244
+ ``NETWORK_STYLE_TEMPLATE``.
245
+ max_words : int, optional
246
+ Maximum number of words to include in the word cloud. The default is ``50``.
247
+ stopwords : Iterable[str], optional
248
+ Stopwords to exclude from the word cloud. The default is ``None``.
249
+ figsize : tuple[float, float], optional
250
+ Size of the composite figure. The default is ``FIG_SIZE``.
251
+
252
+ Returns
253
+ -------
254
+ Figure
255
+ Matplotlib figure containing the word cloud on top and network below.
256
+ """
257
+ validate_dataframe(nodes_df, cols=[text_column], sort_by=node_weight)
258
+ validate_dataframe(edges_df, cols=[source, target, edge_weight], sort_by=None)
259
+
260
+ fig = cast(Figure, plt.figure(figsize=figsize))
261
+ fig.patch.set_facecolor(wordcloud_style.background_color)
262
+ grid = GridSpec(2, 1, height_ratios=[1, 2])
263
+
264
+ wordcloud_ax = fig.add_subplot(grid[0, 0])
265
+ aplot_wordcloud(
266
+ pd_df=nodes_df,
267
+ text_column=text_column,
268
+ weight_column=node_weight,
269
+ title=wordcloud_title,
270
+ style=wordcloud_style,
271
+ max_words=max_words,
272
+ stopwords=stopwords,
273
+ ax=wordcloud_ax,
274
+ )
275
+
276
+ network_ax = fig.add_subplot(grid[1, 0])
277
+ aplot_network(
278
+ pd_df=edges_df,
279
+ source=source,
280
+ target=target,
281
+ weight=edge_weight,
282
+ title=network_title,
283
+ style=network_style,
284
+ ax=network_ax,
285
+ )
286
+
287
+ fig.tight_layout()
288
+ return fig
@@ -14,6 +14,7 @@ from matplotlib.figure import Figure
14
14
 
15
15
  from .StyleTemplate import (
16
16
  NETWORK_STYLE_TEMPLATE,
17
+ FIG_SIZE,
17
18
  StyleTemplate,
18
19
  format_func,
19
20
  string_formatter,
@@ -410,7 +411,25 @@ class NetworkGraph:
410
411
  if ax is None:
411
412
  ax = cast(Axes, plt.gca())
412
413
 
413
- node_sizes, edge_widths, font_sizes = self.layout(
414
+ isolated_nodes = list(nx.isolates(self._nx_graph))
415
+ graph_nx = self._nx_graph
416
+ if isolated_nodes:
417
+ # Avoid mutating the user-provided graph when pruning display-only
418
+ # isolates so the underlying data remains unchanged after plotting.
419
+ graph_nx = graph_nx.copy()
420
+ graph_nx.remove_nodes_from(isolated_nodes)
421
+
422
+ graph = self if graph_nx is self._nx_graph else NetworkGraph(graph_nx)
423
+
424
+ if graph._nx_graph.number_of_nodes() == 0:
425
+ ax.set_axis_off()
426
+ if title:
427
+ ax.set_title(
428
+ title, color=style.font_color, fontsize=style.font_size * 2
429
+ )
430
+ return ax
431
+
432
+ node_sizes, edge_widths, font_sizes = graph.layout(
414
433
  min_node_size=DEFAULT["MIN_NODE_SIZE"] // 5,
415
434
  max_node_size=DEFAULT["MAX_NODE_SIZE"],
416
435
  max_edge_width=DEFAULT["MAX_EDGE_WIDTH"],
@@ -418,11 +437,11 @@ class NetworkGraph:
418
437
  max_font_size=style.font_mapping.get(4, DEFAULT["MAX_FONT_SIZE"]),
419
438
  weight=weight,
420
439
  )
421
- pos = nx.spring_layout(self._nx_graph, k=1)
440
+ pos = nx.spring_layout(graph._nx_graph, k=1)
422
441
  # nodes
423
442
  node_sizes_int = [int(size) for size in node_sizes]
424
443
  nx.draw_networkx_nodes(
425
- self._nx_graph,
444
+ graph._nx_graph,
426
445
  pos,
427
446
  ax=ax,
428
447
  node_size=cast(Any, node_sizes_int),
@@ -431,7 +450,7 @@ class NetworkGraph:
431
450
  )
432
451
  # edges
433
452
  nx.draw_networkx_edges(
434
- self._nx_graph,
453
+ graph._nx_graph,
435
454
  pos,
436
455
  ax=ax,
437
456
  edge_color=style.font_color,
@@ -441,7 +460,7 @@ class NetworkGraph:
441
460
  # labels
442
461
  for font_size, nodes in font_sizes.items():
443
462
  nx.draw_networkx_labels(
444
- self._nx_graph,
463
+ graph._nx_graph,
445
464
  pos,
446
465
  ax=ax,
447
466
  font_size=font_size,
@@ -614,7 +633,7 @@ def compute_network_grid(
614
633
  n_components = len(connected_components)
615
634
  n_cols = int(np.ceil(np.sqrt(n_components)))
616
635
  n_rows = int(np.ceil(n_components / n_cols))
617
- fig, axes_grid = plt.subplots(n_rows, n_cols, figsize=(19.2, 10.8))
636
+ fig, axes_grid = plt.subplots(n_rows, n_cols, figsize=FIG_SIZE)
618
637
  fig = cast(Figure, fig)
619
638
  fig.patch.set_facecolor(style.background_color)
620
639
  if not isinstance(axes_grid, np.ndarray):
@@ -767,6 +786,20 @@ def aplot_network_components(
767
786
 
768
787
  connected_components = list(nx.connected_components(graph._nx_graph))
769
788
 
789
+ if not connected_components:
790
+ if axes is not None:
791
+ for ax in axes.flatten():
792
+ ax.set_axis_off()
793
+ return
794
+
795
+ isolated_nodes = list(nx.isolates(graph._nx_graph))
796
+ if isolated_nodes:
797
+ # Keep the caller's graph intact while dropping isolates purely for
798
+ # visualization.
799
+ graph = NetworkGraph(graph._nx_graph.copy())
800
+ graph._nx_graph.remove_nodes_from(isolated_nodes)
801
+ connected_components = list(nx.connected_components(graph._nx_graph))
802
+
770
803
  if not connected_components:
771
804
  if axes is not None:
772
805
  for ax in axes.flatten():
@@ -806,7 +839,7 @@ def fplot_network(
806
839
  sort_by: Optional[str] = None,
807
840
  ascending: bool = False,
808
841
  node_list: Optional[List] = None,
809
- figsize: Tuple[float, float] = (19.2, 10.8),
842
+ figsize: Tuple[float, float] = FIG_SIZE,
810
843
  save_path: Optional[str] = None,
811
844
  savefig_kwargs: Optional[Dict[str, Any]] = None,
812
845
  ) -> Figure:
@@ -833,7 +866,7 @@ def fplot_network(
833
866
  node_list : list, optional
834
867
  Nodes to include.
835
868
  figsize : tuple[float, float], optional
836
- Size of the created figure. The default is (19.2, 10.8).
869
+ Size of the created figure. The default is FIG_SIZE.
837
870
 
838
871
  Returns
839
872
  -------
@@ -870,7 +903,7 @@ def fplot_network_components(
870
903
  sort_by: Optional[str] = None,
871
904
  ascending: bool = False,
872
905
  node_list: Optional[List] = None,
873
- figsize: Tuple[float, float] = (19.2, 10.8),
906
+ figsize: Tuple[float, float] = FIG_SIZE,
874
907
  n_cols: Optional[int] = None,
875
908
  save_path: Optional[str] = None,
876
909
  savefig_kwargs: Optional[Dict[str, Any]] = None,
@@ -898,7 +931,7 @@ def fplot_network_components(
898
931
  node_list : list, optional
899
932
  Nodes to include.
900
933
  figsize : tuple[float, float], optional
901
- Size of the created figure. The default is (19.2, 10.8).
934
+ Size of the created figure. The default is FIG_SIZE.
902
935
  n_cols : int, optional
903
936
  Number of columns for subplots. If None, it's inferred.
904
937
 
@@ -8,7 +8,7 @@ from matplotlib.figure import Figure
8
8
  from matplotlib.transforms import Bbox
9
9
  from matplotlib.table import Table
10
10
 
11
- from .StyleTemplate import StyleTemplate, string_formatter, validate_dataframe
11
+ from .StyleTemplate import StyleTemplate, string_formatter, validate_dataframe, FIG_SIZE
12
12
 
13
13
  TABLE_STYLE_TEMPLATE = StyleTemplate(
14
14
  background_color="black", fig_border="darkgrey", font_color="white", palette="magma"
@@ -172,7 +172,7 @@ def fplot_table(
172
172
  max_values: int = 20,
173
173
  sort_by: Optional[str] = None,
174
174
  ascending: bool = False,
175
- figsize: Tuple[float, float] = (19.2, 10.8),
175
+ figsize: Tuple[float, float] = FIG_SIZE,
176
176
  save_path: Optional[str] = None,
177
177
  savefig_kwargs: Optional[Dict[str, Any]] = None,
178
178
  ) -> Figure:
@@ -195,7 +195,7 @@ def fplot_table(
195
195
  ascending : bool, optional
196
196
  Sort order for the data, by default ``False``.
197
197
  figsize : tuple of float, optional
198
- Size of the created figure, by default ``(19.2, 10.8)``.
198
+ Size of the created figure, by default ``FIG_SIZE``.
199
199
 
200
200
  Returns
201
201
  -------
@@ -10,6 +10,7 @@ from matplotlib.figure import Figure
10
10
 
11
11
  from .StyleTemplate import (
12
12
  TIMESERIE_STYLE_TEMPLATE,
13
+ FIG_SIZE,
13
14
  StyleTemplate,
14
15
  bmk_formatter,
15
16
  format_func,
@@ -269,7 +270,7 @@ def fplot_timeserie(
269
270
  sort_by: Optional[str] = None,
270
271
  ascending: bool = False,
271
272
  std: bool = False,
272
- figsize: Tuple[float, float] = (19.2, 10.8),
273
+ figsize: Tuple[float, float] = FIG_SIZE,
273
274
  save_path: Optional[str] = None,
274
275
  savefig_kwargs: Optional[Dict[str, Any]] = None,
275
276
  ) -> Figure:
@@ -298,7 +299,7 @@ def fplot_timeserie(
298
299
  std : bool, optional
299
300
  Whether to plot rolling standard deviation. The default is `False`.
300
301
  figsize : tuple[float, float], optional
301
- Size of the created figure. The default is (19.2, 10.8).
302
+ Size of the created figure. The default is FIG_SIZE.
302
303
 
303
304
  Returns
304
305
  -------
@@ -187,20 +187,17 @@ def _plot_words(
187
187
 
188
188
  canvas.draw()
189
189
  ax_bbox = ax.get_window_extent()
190
- resolved_mask = create_circular_mask() if mask is None else np.asarray(mask)
191
- if resolved_mask is not None and resolved_mask.ndim != 2:
190
+
191
+ if mask is None:
192
+ mask_dimension = max(int(ax_bbox.width), int(ax_bbox.height), 1)
193
+ resolved_mask = create_circular_mask(size=mask_dimension)
194
+ else:
195
+ resolved_mask = np.asarray(mask)
196
+
197
+ if resolved_mask.ndim != 2:
192
198
  raise ValueError("mask must be a 2D array.")
193
199
 
194
- width = (
195
- max(int(ax_bbox.width), 1)
196
- if resolved_mask is None
197
- else max(int(resolved_mask.shape[1]), 1)
198
- )
199
- height = (
200
- max(int(ax_bbox.height), 1)
201
- if resolved_mask is None
202
- else max(int(resolved_mask.shape[0]), 1)
203
- )
200
+ height, width = resolved_mask.shape
204
201
 
205
202
  frequency_map = {
206
203
  string_formatter(word): weight for word, weight in zip(words, weights)
@@ -4,7 +4,11 @@ from .Area import aplot_area, fplot_area
4
4
  from .Bar import aplot_bar, fplot_bar
5
5
  from .BoxViolin import aplot_box_violin, fplot_box_violin
6
6
  from .Bubble import BUBBLE_STYLE_TEMPLATE, aplot_bubble, fplot_bubble
7
- from .Composite import plot_composite_bubble, plot_composite_treemap
7
+ from .Composite import (
8
+ plot_composite_bubble,
9
+ plot_composite_treemap,
10
+ plot_wordcloud_network,
11
+ )
8
12
  from .Heatmap import (
9
13
  HEATMAP_STYLE_TEMPLATE,
10
14
  aplot_correlation_matrix,
@@ -80,5 +84,6 @@ __all__ = [
80
84
  "fplot_sankey",
81
85
  "plot_composite_bubble",
82
86
  "plot_composite_treemap",
87
+ "plot_wordcloud_network",
83
88
  "prepare_network_graph",
84
89
  ]
@@ -32,6 +32,7 @@ from .Network import (
32
32
  from .Pie import aplot_pie_donut, fplot_pie_donut
33
33
  from .Sankey import SANKEY_STYLE_TEMPLATE, fplot_sankey
34
34
  from .StyleTemplate import (
35
+ FIG_SIZE,
35
36
  AREA_STYLE_TEMPLATE,
36
37
  DISTRIBUTION_STYLE_TEMPLATE,
37
38
  PIE_STYLE_TEMPLATE,
@@ -210,7 +211,7 @@ class DataFrameAccessor:
210
211
  ascending: bool = False,
211
212
  hline: bool = False,
212
213
  vline: bool = False,
213
- figsize: Tuple[float, float] = (19.2, 10.8),
214
+ figsize: Tuple[float, float] = FIG_SIZE,
214
215
  save_path: Optional[str] = None,
215
216
  savefig_kwargs: Optional[Dict[str, Any]] = None,
216
217
  ) -> Figure:
@@ -243,7 +244,7 @@ class DataFrameAccessor:
243
244
  vline : bool, optional
244
245
  If True, draw a vertical line at the mean of x-values. The default is `False`.
245
246
  figsize : tuple[float, float], optional
246
- Figure size. The default is (19.2, 10.8).
247
+ Figure size. The default is FIG_SIZE.
247
248
 
248
249
  Returns
249
250
  -------
@@ -386,7 +387,7 @@ class DataFrameAccessor:
386
387
  stacked: bool = False,
387
388
  title: Optional[str] = None,
388
389
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
389
- figsize: Tuple[float, float] = (19.2, 10.8),
390
+ figsize: Tuple[float, float] = FIG_SIZE,
390
391
  ) -> Figure:
391
392
  """Plot bar or stacked bar charts on a new figure.
392
393
 
@@ -405,7 +406,7 @@ class DataFrameAccessor:
405
406
  style : StyleTemplate, optional
406
407
  Styling template. The default is ``DISTRIBUTION_STYLE_TEMPLATE``.
407
408
  figsize : tuple[float, float], optional
408
- Figure size. The default is (19.2, 10.8).
409
+ Figure size. The default is FIG_SIZE.
409
410
 
410
411
  Returns
411
412
  -------
@@ -471,7 +472,7 @@ class DataFrameAccessor:
471
472
  kde: bool = True,
472
473
  title: Optional[str] = None,
473
474
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
474
- figsize: Tuple[float, float] = (19.2, 10.8),
475
+ figsize: Tuple[float, float] = FIG_SIZE,
475
476
  ) -> Figure:
476
477
  """Plot a histogram with an optional KDE on a new figure.
477
478
 
@@ -488,7 +489,7 @@ class DataFrameAccessor:
488
489
  style : StyleTemplate, optional
489
490
  Styling template. The default is ``DISTRIBUTION_STYLE_TEMPLATE``.
490
491
  figsize : tuple[float, float], optional
491
- Figure size. The default is (19.2, 10.8).
492
+ Figure size. The default is FIG_SIZE.
492
493
 
493
494
  Returns
494
495
  -------
@@ -553,7 +554,7 @@ class DataFrameAccessor:
553
554
  violin: bool = False,
554
555
  title: Optional[str] = None,
555
556
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
556
- figsize: Tuple[float, float] = (19.2, 10.8),
557
+ figsize: Tuple[float, float] = FIG_SIZE,
557
558
  ) -> Figure:
558
559
  """Plot box or violin charts on a new figure.
559
560
 
@@ -570,7 +571,7 @@ class DataFrameAccessor:
570
571
  style : StyleTemplate, optional
571
572
  Styling template. The default is ``DISTRIBUTION_STYLE_TEMPLATE``.
572
573
  figsize : tuple[float, float], optional
573
- Figure size. The default is (19.2, 10.8).
574
+ Figure size. The default is FIG_SIZE.
574
575
 
575
576
  Returns
576
577
  -------
@@ -635,7 +636,7 @@ class DataFrameAccessor:
635
636
  value: str,
636
637
  title: Optional[str] = None,
637
638
  style: StyleTemplate = HEATMAP_STYLE_TEMPLATE,
638
- figsize: Tuple[float, float] = (19.2, 10.8),
639
+ figsize: Tuple[float, float] = FIG_SIZE,
639
640
  ) -> Figure:
640
641
  """Plot a heatmap on a new figure.
641
642
 
@@ -652,7 +653,7 @@ class DataFrameAccessor:
652
653
  style : StyleTemplate, optional
653
654
  Styling template. The default is ``HEATMAP_STYLE_TEMPLATE``.
654
655
  figsize : tuple[float, float], optional
655
- Figure size. The default is (19.2, 10.8).
656
+ Figure size. The default is FIG_SIZE.
656
657
 
657
658
  Returns
658
659
  -------
@@ -712,7 +713,7 @@ class DataFrameAccessor:
712
713
  method: CorrelationMethod = "pearson",
713
714
  title: Optional[str] = None,
714
715
  style: StyleTemplate = HEATMAP_STYLE_TEMPLATE,
715
- figsize: Tuple[float, float] = (19.2, 10.8),
716
+ figsize: Tuple[float, float] = FIG_SIZE,
716
717
  ) -> Figure:
717
718
  """Plot a correlation matrix heatmap on a new figure.
718
719
 
@@ -727,7 +728,7 @@ class DataFrameAccessor:
727
728
  style : StyleTemplate, optional
728
729
  Styling template. The default is ``HEATMAP_STYLE_TEMPLATE``.
729
730
  figsize : tuple[float, float], optional
730
- Figure size. The default is (19.2, 10.8).
731
+ Figure size. The default is FIG_SIZE.
731
732
 
732
733
  Returns
733
734
  -------
@@ -796,7 +797,7 @@ class DataFrameAccessor:
796
797
  stacked: bool = True,
797
798
  title: Optional[str] = None,
798
799
  style: StyleTemplate = AREA_STYLE_TEMPLATE,
799
- figsize: Tuple[float, float] = (19.2, 10.8),
800
+ figsize: Tuple[float, float] = FIG_SIZE,
800
801
  ) -> Figure:
801
802
  """Plot an area chart on a new figure.
802
803
 
@@ -815,7 +816,7 @@ class DataFrameAccessor:
815
816
  style : StyleTemplate, optional
816
817
  Styling template. The default is ``AREA_STYLE_TEMPLATE``.
817
818
  figsize : tuple[float, float], optional
818
- Figure size. The default is (19.2, 10.8).
819
+ Figure size. The default is FIG_SIZE.
819
820
 
820
821
  Returns
821
822
  -------
@@ -881,7 +882,7 @@ class DataFrameAccessor:
881
882
  donut: bool = False,
882
883
  title: Optional[str] = None,
883
884
  style: StyleTemplate = PIE_STYLE_TEMPLATE,
884
- figsize: Tuple[float, float] = (19.2, 10.8),
885
+ figsize: Tuple[float, float] = FIG_SIZE,
885
886
  ) -> Figure:
886
887
  """Plot pie or donut charts on a new figure.
887
888
 
@@ -898,7 +899,7 @@ class DataFrameAccessor:
898
899
  style : StyleTemplate, optional
899
900
  Styling template. The default is ``PIE_STYLE_TEMPLATE``.
900
901
  figsize : tuple[float, float], optional
901
- Figure size. The default is (19.2, 10.8).
902
+ Figure size. The default is FIG_SIZE.
902
903
 
903
904
  Returns
904
905
  -------
@@ -963,7 +964,7 @@ class DataFrameAccessor:
963
964
  rows: int = 10,
964
965
  title: Optional[str] = None,
965
966
  style: StyleTemplate = PIE_STYLE_TEMPLATE,
966
- figsize: Tuple[float, float] = (19.2, 10.8),
967
+ figsize: Tuple[float, float] = FIG_SIZE,
967
968
  ) -> Figure:
968
969
  """Plot waffle charts on a new figure.
969
970
 
@@ -980,7 +981,7 @@ class DataFrameAccessor:
980
981
  style : StyleTemplate, optional
981
982
  Styling template. The default is ``PIE_STYLE_TEMPLATE``.
982
983
  figsize : tuple[float, float], optional
983
- Figure size. The default is (19.2, 10.8).
984
+ Figure size. The default is FIG_SIZE.
984
985
 
985
986
  Returns
986
987
  -------
@@ -1087,7 +1088,7 @@ class DataFrameAccessor:
1087
1088
  max_values: int = 20,
1088
1089
  sort_by: Optional[str] = None,
1089
1090
  ascending: bool = False,
1090
- figsize: Tuple[float, float] = (19.2, 10.8),
1091
+ figsize: Tuple[float, float] = FIG_SIZE,
1091
1092
  ) -> Figure:
1092
1093
  """Plot a table of the DataFrame's data on a new figure.
1093
1094
 
@@ -1106,7 +1107,7 @@ class DataFrameAccessor:
1106
1107
  ascending : bool, optional
1107
1108
  Sort order. The default is `False`.
1108
1109
  figsize : tuple[float, float], optional
1109
- Figure size. The default is (19.2, 10.8).
1110
+ Figure size. The default is FIG_SIZE.
1110
1111
 
1111
1112
  Returns
1112
1113
  -------
@@ -1192,7 +1193,7 @@ class DataFrameAccessor:
1192
1193
  sort_by: Optional[str] = None,
1193
1194
  ascending: bool = False,
1194
1195
  std: bool = False,
1195
- figsize: Tuple[float, float] = (19.2, 10.8),
1196
+ figsize: Tuple[float, float] = FIG_SIZE,
1196
1197
  ) -> Figure:
1197
1198
  """Plot a time series on a new figure.
1198
1199
 
@@ -1217,7 +1218,7 @@ class DataFrameAccessor:
1217
1218
  std : bool, optional
1218
1219
  If True, plot the standard deviation. The default is `False`.
1219
1220
  figsize : tuple[float, float], optional
1220
- Figure size. The default is (19.2, 10.8).
1221
+ Figure size. The default is FIG_SIZE.
1221
1222
 
1222
1223
  Returns
1223
1224
  -------
@@ -1296,7 +1297,7 @@ class DataFrameAccessor:
1296
1297
  max_words: int = 50,
1297
1298
  stopwords: Optional[List[str]] = None,
1298
1299
  random_state: Optional[int] = None,
1299
- figsize: Tuple[float, float] = (19.2, 10.8),
1300
+ figsize: Tuple[float, float] = FIG_SIZE,
1300
1301
  ) -> Figure:
1301
1302
  """Plot a word cloud on a new figure.
1302
1303
 
@@ -1317,7 +1318,7 @@ class DataFrameAccessor:
1317
1318
  random_state : int, optional
1318
1319
  Seed for word placement. The default is ``None``.
1319
1320
  figsize : tuple[float, float], optional
1320
- Figure size. The default is (19.2, 10.8).
1321
+ Figure size. The default is FIG_SIZE.
1321
1322
 
1322
1323
  Returns
1323
1324
  -------
@@ -1447,7 +1448,7 @@ class DataFrameAccessor:
1447
1448
  sort_by: Optional[str] = None,
1448
1449
  ascending: bool = False,
1449
1450
  node_list: Optional[List] = None,
1450
- figsize: Tuple[float, float] = (19.2, 10.8),
1451
+ figsize: Tuple[float, float] = FIG_SIZE,
1451
1452
  ) -> Figure:
1452
1453
  """Plot a network graph on a new figure.
1453
1454
 
@@ -1470,7 +1471,7 @@ class DataFrameAccessor:
1470
1471
  node_list : list, optional
1471
1472
  List of nodes to include. If None, all nodes are used.
1472
1473
  figsize : tuple[float, float], optional
1473
- Figure size. The default is (19.2, 10.8).
1474
+ Figure size. The default is FIG_SIZE.
1474
1475
 
1475
1476
  Returns
1476
1477
  -------
@@ -1500,7 +1501,7 @@ class DataFrameAccessor:
1500
1501
  sort_by: Optional[str] = None,
1501
1502
  ascending: bool = False,
1502
1503
  node_list: Optional[List] = None,
1503
- figsize: Tuple[float, float] = (19.2, 10.8),
1504
+ figsize: Tuple[float, float] = FIG_SIZE,
1504
1505
  n_cols: Optional[int] = None,
1505
1506
  ) -> Figure:
1506
1507
  """Plot network components on a new figure.
@@ -1524,7 +1525,7 @@ class DataFrameAccessor:
1524
1525
  node_list : list, optional
1525
1526
  List of nodes to include. If None, all nodes are used.
1526
1527
  figsize : tuple[float, float], optional
1527
- Figure size. The default is (19.2, 10.8).
1528
+ Figure size. The default is FIG_SIZE.
1528
1529
  n_cols : int, optional
1529
1530
  Number of columns for arranging component subplots.
1530
1531
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MatplotLibAPI
3
- Version: 3.2.20
3
+ Version: 3.2.21
4
4
  License-File: LICENSE
5
5
  Requires-Python: >=3.8
6
6
  Requires-Dist: kaleido
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
  [project]
5
5
  name = "MatplotLibAPI"
6
- version = "3.2.20"
6
+ version = "3.2.21"
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.8"
9
9
  dependencies = [
@@ -1,6 +1,9 @@
1
1
  """Tests for word cloud visualizations."""
2
2
 
3
+ from typing import cast
4
+
3
5
  import matplotlib.pyplot as plt
6
+ from matplotlib.axes import Axes
4
7
  from matplotlib.figure import Figure
5
8
  import numpy as np
6
9
 
@@ -16,15 +19,21 @@ def test_fplot_wordcloud(load_sample_df):
16
19
 
17
20
  df = load_sample_df("wordcloud.csv")
18
21
 
19
- fig = fplot_wordcloud(
20
- pd_df=df, text_column="country", weight_column="population", random_state=42
22
+ fig = cast(
23
+ Figure,
24
+ fplot_wordcloud(
25
+ pd_df=df, text_column="country", weight_column="population", random_state=42
26
+ ),
21
27
  )
22
28
 
23
- assert isinstance(fig, Figure)
24
- default_mask = create_circular_mask(size=300)
25
- image = fig.axes[0].images[0].get_array()
29
+ fig.canvas.draw()
30
+ ax = cast(Axes, fig.axes[0])
31
+ expected_size = int(
32
+ max(ax.get_window_extent().width, ax.get_window_extent().height)
33
+ )
34
+ image = ax.images[0].get_array()
26
35
  assert image is not None
27
- assert tuple(image.shape[:2]) == default_mask.shape
36
+ assert image.shape[0] == image.shape[1] >= expected_size
28
37
 
29
38
 
30
39
  def test_fplot_wordcloud_with_mask(load_sample_df):
@@ -33,15 +42,18 @@ def test_fplot_wordcloud_with_mask(load_sample_df):
33
42
  df = load_sample_df("wordcloud.csv")
34
43
  mask = create_circular_mask(size=200)
35
44
 
36
- fig = fplot_wordcloud(
37
- pd_df=df,
38
- text_column="country",
39
- weight_column="population",
40
- random_state=0,
41
- mask=mask,
45
+ fig = cast(
46
+ Figure,
47
+ fplot_wordcloud(
48
+ pd_df=df,
49
+ text_column="country",
50
+ weight_column="population",
51
+ random_state=0,
52
+ mask=mask,
53
+ ),
42
54
  )
43
55
 
44
- image = fig.axes[0].images[0].get_array()
56
+ image = cast(Axes, fig.axes[0]).images[0].get_array()
45
57
  assert image is not None
46
58
  assert tuple(image.shape[:2]) == mask.shape
47
59
 
@@ -51,6 +63,8 @@ def test_aplot_wordcloud(load_sample_df):
51
63
 
52
64
  df = load_sample_df("wordcloud.csv")
53
65
  fig, ax = plt.subplots()
66
+ fig = cast(Figure, fig)
67
+ ax = cast(Axes, ax)
54
68
 
55
69
  result_ax = aplot_wordcloud(
56
70
  ax=ax,
@@ -62,9 +76,13 @@ def test_aplot_wordcloud(load_sample_df):
62
76
 
63
77
  assert result_ax is not None
64
78
  assert ax is result_ax
79
+ fig.canvas.draw()
80
+ expected_size = int(
81
+ max(ax.get_window_extent().width, ax.get_window_extent().height)
82
+ )
65
83
  image = result_ax.images[0].get_array()
66
84
  assert image is not None
67
- assert image.shape[0] > 0 and image.shape[1] > 0
85
+ assert image.shape[0] == image.shape[1] >= expected_size
68
86
 
69
87
 
70
88
  def test_create_circular_mask():
File without changes
File without changes
File without changes