MatplotLibAPI 3.2.8__py3-none-any.whl → 3.2.10__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  # Hint for Visual Code Python Interactive window
2
2
  # %%
3
- from typing import Optional, Tuple, List
3
+ from typing import Optional, Tuple, List, Dict
4
4
  import pandas as pd
5
5
  import matplotlib.pyplot as plt
6
6
  from matplotlib.figure import Figure
@@ -27,7 +27,53 @@ def plot_composite_bubble(
27
27
  ascending: bool = False,
28
28
  table_rows: int = 10,
29
29
  figsize: Tuple[float, float] = (19.2, 10.8)) -> Figure:
30
+ """
31
+ Plot a composite bubble chart with additional tables for top and bottom values.
30
32
 
33
+ Parameters:
34
+ pd_df (pd.DataFrame):
35
+ The pandas DataFrame containing the data to be plotted.
36
+ label (str):
37
+ The column name for the bubble labels.
38
+ x (str):
39
+ The column name for the x-axis values.
40
+ y (str):
41
+ The column name for the y-axis values.
42
+ z (str):
43
+ The column name for the bubble sizes.
44
+ title (Optional[str]):
45
+ The title of the plot. Default is "Test".
46
+ style (StyleTemplate):
47
+ A StyleTemplate object to define the visual style of the plot. Default is BUBBLE_STYLE_TEMPLATE.
48
+ max_values (int):
49
+ The maximum number of values to display in the bubble chart. Default is 50.
50
+ center_to_mean (bool):
51
+ A flag indicating whether to center the bubbles to the mean. Default is False.
52
+ filter_by (Optional[str]):
53
+ The column name to filter the data by. Default is None.
54
+ sort_by (Optional[str]):
55
+ The column name to sort the data by. Default is None.
56
+ ascending (bool):
57
+ A flag indicating whether to sort in ascending order. Default is False.
58
+ table_rows (int):
59
+ The number of rows to display in the tables. Default is 10.
60
+ figsize (Tuple[float, float]):
61
+ The size of the figure. Default is (19.2, 10.8).
62
+
63
+ Returns:
64
+ Figure:
65
+ The matplotlib figure object containing the composite bubble chart and tables.
66
+
67
+ Example:
68
+ >>> df = pd.DataFrame({
69
+ ... "Label": ["A", "B", "C"],
70
+ ... "X": [1, 2, 3],
71
+ ... "Y": [4, 5, 6],
72
+ ... "Z": [7, 8, 9]
73
+ ... })
74
+ >>> fig = plot_composite_bubble(df, label="Label", x="X", y="Y", z="Z")
75
+ >>> fig.show()
76
+ """
31
77
  validate_dataframe(pd_df, cols=[label, x, y, z], sort_by=sort_by)
32
78
 
33
79
  if not sort_by:
@@ -90,35 +136,61 @@ def plot_composite_bubble(
90
136
  return fig
91
137
 
92
138
 
93
- def plot_composite_treemap(pd_dfs: List[pd.DataFrame],
94
- path: str,
95
- values: str,
96
- style: StyleTemplate = TREEMAP_STYLE_TEMPLATE,
97
- title: Optional[str] = None,
98
- color: Optional[str] = None,
99
- sort_by: Optional[str] = None,
100
- ascending: bool = False,
101
- max_values: int = 100) -> go.Figure:
139
+ def plot_composite_treemap(pd_dfs: Dict[str, pd.DataFrame],
140
+ values: str,
141
+ style: StyleTemplate = TREEMAP_STYLE_TEMPLATE,
142
+ title: Optional[str] = None,
143
+ color: Optional[str] = None,
144
+ sort_by: Optional[str] = None,
145
+ ascending: bool = False,
146
+ max_values: int = 100) -> Optional[go.Figure]:
147
+ """
148
+ Plot a composite treemap from multiple DataFrames.
149
+
150
+ Parameters:
151
+ pd_dfs (Dict[str, pd.DataFrame]):
152
+ A dictionary where keys are dimension names and values are pandas DataFrames to be plotted.
153
+ values (str):
154
+ The column name in each DataFrame that contains the values to be visualized in the treemap.
155
+ style (StyleTemplate):
156
+ A StyleTemplate object to define the visual style of the treemap. Default is TREEMAP_STYLE_TEMPLATE.
157
+ title (Optional[str]):
158
+ An optional title for the composite treemap plot. Default is None.
159
+ color (Optional[str]):
160
+ An optional column name for coloring the treemap. Default is None.
161
+ sort_by (Optional[str]):
162
+ An optional column name for sorting the treemap values. Default is None.
163
+ ascending (bool):
164
+ A flag indicating whether to sort in ascending order. Default is False.
165
+ max_values (int):
166
+ The maximum number of values to display in each treemap. Default is 100.
102
167
 
168
+ Returns:
169
+ Optional[go.Figure]:
170
+ The composite treemap figure object or None if no DataFrames are provided.
171
+ """
103
172
  num_dimensions = len(pd_dfs)
104
173
  if num_dimensions > 0:
174
+ subplot_titles = [f"{title}::{dim.title()}" if title is not None else dim.title(
175
+ ) for dim in pd_dfs.keys()]
105
176
  fig = make_subplots(
106
177
  rows=num_dimensions,
107
178
  cols=1,
108
- specs=[[{'type': 'domain'}] for _ in range(num_dimensions)],
109
- vertical_spacing=0.02
179
+ specs = [[{"type": "treemap"} for _ in range(0, 1)] for _ in range(0, num_dimensions)],
180
+ subplot_titles=subplot_titles,
181
+ vertical_spacing=0.2
110
182
  )
111
- current_row = 1
112
- for pd_df in pd_dfs:
113
- trm = aplot_treemap(pd_df=pd_df,
114
- path=path,
115
- values=values,
116
- title=title,
117
- style=style,
118
- color=color,
119
- sort_by=sort_by,
120
- ascending=ascending,
121
- max_values=max_values)
122
- fig.add_trace(trm,row=current_row, col=1)
123
- current_row += 1
124
- return fig
183
+
184
+ current_row = 1
185
+ for path, df in pd_dfs.items():
186
+ trm = aplot_treemap(pd_df=df,
187
+ path=path,
188
+ values=values,
189
+ style=style,
190
+ color=color,
191
+ sort_by=sort_by,
192
+ ascending=ascending,
193
+ max_values=max_values)
194
+ fig.add_trace(trm, row=current_row, col=1)
195
+ current_row += 1
196
+ return fig
@@ -10,9 +10,30 @@ from matplotlib.ticker import FuncFormatter
10
10
 
11
11
  # region Utils
12
12
 
13
+
13
14
  def validate_dataframe(pd_df: pd.DataFrame,
14
15
  cols: List[str],
15
16
  sort_by: Optional[str] = None):
17
+ """
18
+ Validate that specified columns exist in a pandas DataFrame and optionally check for a sorting column.
19
+
20
+ Parameters:
21
+ pd_df (pd.DataFrame): The pandas DataFrame to validate.
22
+ cols (List[str]): A list of column names that must exist in the DataFrame.
23
+ sort_by (Optional[str]): An optional column name that, if provided, must also exist in the DataFrame.
24
+
25
+ Raises:
26
+ AttributeError: If any of the specified columns or the sorting column (if provided) do not exist in the DataFrame.
27
+
28
+ Example:
29
+ >>> import pandas as pd
30
+ >>> data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
31
+ >>> df = pd.DataFrame(data)
32
+ >>> validate_dataframe(df, ['A', 'B']) # No error
33
+ >>> validate_dataframe(df, ['A', 'C']) # Raises AttributeError
34
+ >>> validate_dataframe(df, ['A'], sort_by='B') # No error
35
+ >>> validate_dataframe(df, ['A'], sort_by='C') # Raises AttributeError
36
+ """
16
37
  _columns = cols.copy()
17
38
  if sort_by and sort_by not in _columns:
18
39
  _columns.append(sort_by)
@@ -27,6 +48,41 @@ def format_func(
27
48
  x: Optional[str] = None,
28
49
  y: Optional[str] = None,
29
50
  z: Optional[str] = None):
51
+ """
52
+ Update the formatting functions for specified keys if they exist in the provided format functions dictionary.
53
+
54
+ Parameters:
55
+ format_funcs (Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]]):
56
+ A dictionary mapping keys to formatting functions. The keys can be 'label', 'x', 'y', and 'z'.
57
+ label (Optional[str]):
58
+ The key to update with the 'label' formatting function from the dictionary.
59
+ x (Optional[str]):
60
+ The key to update with the 'x' formatting function from the dictionary.
61
+ y (Optional[str]):
62
+ The key to update with the 'y' formatting function from the dictionary.
63
+ z (Optional[str]):
64
+ The key to update with the 'z' formatting function from the dictionary.
65
+
66
+ Returns:
67
+ Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]]:
68
+ The updated dictionary with the specified keys pointing to their corresponding formatting functions.
69
+
70
+ Example:
71
+ >>> format_funcs = {
72
+ ... "label": lambda x: f"Label: {x}",
73
+ ... "x": lambda x: f"X-axis: {x}",
74
+ ... "y": lambda y: f"Y-axis: {y}",
75
+ ... }
76
+ >>> updated_funcs = format_func(format_funcs, label="new_label", x="new_x")
77
+ >>> print(updated_funcs)
78
+ {
79
+ "label": lambda x: f"Label: {x}",
80
+ "x": lambda x: f"X-axis: {x}",
81
+ "y": lambda y: f"Y-axis: {y}",
82
+ "new_label": lambda x: f"Label: {x}",
83
+ "new_x": lambda x: f"X-axis: {x}",
84
+ }
85
+ """
30
86
 
31
87
  if label and "label" in format_funcs:
32
88
  format_funcs[label] = format_funcs["label"]
@@ -64,13 +120,52 @@ class StyleTemplate:
64
120
  palette: str = PALETTE
65
121
  legend: bool = True
66
122
  xscale: Optional[str] = None
67
- x_ticks: int = 10
123
+ x_ticks: int = 5
68
124
  yscale: Optional[str] = None
69
125
  y_ticks: int = 5
70
126
  format_funcs: Optional[Dict[str, Optional[Callable[[
71
127
  Union[int, float, str]], str]]]] = None
72
128
  col_widths: Optional[List[float]] = None
73
-
129
+ """
130
+ A class to define style templates for data visualization with customizable attributes.
131
+
132
+ Attributes:
133
+ background_color (str):
134
+ The background color for the visualizations. Default is BACKGROUND_COLOR.
135
+ fig_border (str):
136
+ The border color for the figures. Default is BACKGROUND_COLOR.
137
+ font_name (str):
138
+ The name of the font to use. Default is 'Arial'.
139
+ font_size (int):
140
+ The base size of the font. Default is FONT_SIZE.
141
+ font_color (str):
142
+ The color of the font. Default is TEXT_COLOR.
143
+ palette (str):
144
+ The color palette to use. Default is PALETTE.
145
+ legend (bool):
146
+ A flag to determine if the legend should be displayed. Default is True.
147
+ xscale (Optional[str]):
148
+ The scale type for the x-axis. Default is None.
149
+ x_ticks (int):
150
+ The number of ticks on the x-axis. Default is 10.
151
+ yscale (Optional[str]):
152
+ The scale type for the y-axis. Default is None.
153
+ y_ticks (int):
154
+ The number of ticks on the y-axis. Default is 5.
155
+ format_funcs (Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]]):
156
+ A dictionary mapping data keys to formatting functions. Default is None.
157
+ col_widths (Optional[List[float]]):
158
+ A list of column widths. Default is None.
159
+
160
+ Properties:
161
+ font_mapping (dict):
162
+ A dictionary mapping font size levels to specific font sizes.
163
+
164
+ Example:
165
+ >>> template = StyleTemplate()
166
+ >>> template.font_mapping
167
+ {0: FONT_SIZE-3, 1: FONT_SIZE-1, 2: FONT_SIZE, 3: FONT_SIZE+1, 4: FONT_SIZE+3}
168
+ """
74
169
  @property
75
170
  def font_mapping(self):
76
171
  return {0: self.font_size-3,
@@ -81,11 +176,37 @@ class StyleTemplate:
81
176
 
82
177
 
83
178
  class DynamicFuncFormatter(FuncFormatter):
179
+ """
180
+ A class to create a dynamic function formatter for matplotlib plots.
181
+
182
+ Inherits from:
183
+ FuncFormatter: A base class from matplotlib for formatting axis ticks.
184
+
185
+ Parameters:
186
+ func_name (Callable): The function to be used for formatting.
187
+
188
+ Example:
189
+ >>> formatter = DynamicFuncFormatter(percent_formatter)
190
+ """
84
191
  def __init__(self, func_name):
85
192
  super().__init__(func_name)
86
193
 
87
194
 
88
195
  def percent_formatter(val, pos: Optional[int] = None):
196
+ """
197
+ Format a value as a percentage.
198
+
199
+ Parameters:
200
+ val (float): The value to format.
201
+ pos (Optional[int]): The position (not used).
202
+
203
+ Returns:
204
+ str: The formatted percentage string.
205
+
206
+ Example:
207
+ >>> percent_formatter(0.005)
208
+ '1%'
209
+ """
89
210
  if val*100 <= 0.1: # For 0.1%
90
211
  return f"{val*100:.2f}%"
91
212
  elif val*100 <= 1: # For 1%
@@ -95,6 +216,20 @@ def percent_formatter(val, pos: Optional[int] = None):
95
216
 
96
217
 
97
218
  def bmk_formatter(val, pos: Optional[int] = None):
219
+ """
220
+ Format a value as billions, millions, or thousands.
221
+
222
+ Parameters:
223
+ val (float): The value to format.
224
+ pos (Optional[int]): The position (not used).
225
+
226
+ Returns:
227
+ str: The formatted string with B, M, or K suffix.
228
+
229
+ Example:
230
+ >>> bmk_formatter(1500000)
231
+ '1.5M'
232
+ """
98
233
  if val >= 1_000_000_000: # Billions
99
234
  return f"{val / 1_000_000_000:.2f}B"
100
235
  elif val >= 1_000_000: # Millions
@@ -106,26 +241,93 @@ def bmk_formatter(val, pos: Optional[int] = None):
106
241
 
107
242
 
108
243
  def integer_formatter(value, pos: Optional[int] = None):
244
+ """
245
+ Format a value as an integer.
246
+
247
+ Parameters:
248
+ value (float): The value to format.
249
+ pos (Optional[int]): The position (not used).
250
+
251
+ Returns:
252
+ str: The formatted integer string.
253
+
254
+ Example:
255
+ >>> integer_formatter(42.9)
256
+ '42'
257
+ """
109
258
  return f"{int(value)}"
110
259
 
111
260
 
112
261
  def string_formatter(value, pos: Optional[int] = None):
262
+ """
263
+ Format a string by replacing '-' and '_' with spaces and capitalizing words.
264
+
265
+ Parameters:
266
+ value (str): The string to format.
267
+ pos (Optional[int]): The position (not used).
268
+
269
+ Returns:
270
+ str: The formatted string.
271
+
272
+ Example:
273
+ >>> string_formatter("example-string_formatter")
274
+ 'Example String Formatter'
275
+ """
113
276
  return str(value).replace("-", " ").replace("_", " ").title()
114
277
 
115
278
 
116
279
  def yy_mm__formatter(x, pos: Optional[int] = None):
280
+ """
281
+ Format a date as 'YYYY-MM'.
282
+
283
+ Parameters:
284
+ x (float): The value to format.
285
+ pos (Optional[int]): The position (not used).
286
+
287
+ Returns:
288
+ str: The formatted date string.
289
+
290
+ Example:
291
+ >>> yy_mm__formatter(737060)
292
+ '2020-01'
293
+ """
117
294
  return num2date(x).strftime('%Y-%m')
118
295
 
119
296
 
120
297
  def yy_mm_dd__formatter(x, pos: Optional[int] = None):
298
+ """
299
+ Format a date as 'YYYY-MM-DD'.
300
+
301
+ Parameters:
302
+ x (float): The value to format.
303
+ pos (Optional[int]): The position (not used).
304
+
305
+ Returns:
306
+ str: The formatted date string.
307
+
308
+ Example:
309
+ >>> yy_mm_dd__formatter(737060)
310
+ '2020-01-01'
311
+ """
121
312
  return num2date(x).strftime('%Y-%m-%D')
122
313
 
123
314
 
124
- def percent_formatter(x, pos: Optional[int] = None):
125
- return f"{x * 100:.0f}%"
315
+ def generate_ticks(min_val, max_val, num_ticks:int=5):
316
+ """
317
+ Generate tick marks for a given range.
318
+
319
+ Parameters:
320
+ min_val (Union[float, str]): The minimum value of the range.
321
+ max_val (Union[float, str]): The maximum value of the range.
322
+ num_ticks (int): The number of ticks to generate. Default is 10.
126
323
 
324
+ Returns:
325
+ np.ndarray: An array of tick marks.
127
326
 
128
- def generate_ticks(min_val, max_val, num_ticks="10"):
327
+ Example:
328
+ >>> generate_ticks(0, 100, 5)
329
+ array([ 0., 25., 50., 75., 100.])
330
+ """
129
331
  # Identify the type of the input
130
332
  try:
131
333
  min_val = float(min_val)
MatplotLibAPI/__init__.py CHANGED
@@ -1,12 +1,12 @@
1
1
 
2
2
  from .StyleTemplate import StyleTemplate
3
3
  from .Bubble import aplot_bubble, fplot_bubble, BUBBLE_STYLE_TEMPLATE
4
- from .Composite import plot_composite_bubble
4
+ from .Composite import plot_composite_bubble,plot_composite_treemap
5
5
  from .Timeserie import aplot_timeserie, fplot_timeserie, TIMESERIE_STYLE_TEMPLATE
6
6
  from .Table import aplot_table, fplot_table, TABLE_STYLE_TEMPLATE
7
7
  from .Network import aplot_network, aplot_network_components, fplot_network, NETWORK_STYLE_TEMPLATE
8
8
  from .Treemap import fplot_treemap, aplot_treemap, TREEMAP_STYLE_TEMPLATE
9
- from typing import List, Optional, Tuple
9
+ from typing import List, Optional, Tuple,Dict
10
10
  import pandas as pd
11
11
  from pandas.api.extensions import register_dataframe_accessor
12
12
 
@@ -294,6 +294,30 @@ class DataFrameAccessor:
294
294
  ascending=ascending,
295
295
  max_values=max_values)
296
296
 
297
+ def fplot_composite_treemap(self,
298
+ pathes: List[str],
299
+ values: str,
300
+ style: StyleTemplate = TREEMAP_STYLE_TEMPLATE,
301
+ title: Optional[str] = None,
302
+ color: Optional[str] = None,
303
+ sort_by: Optional[str] = None,
304
+ max_values: int = 100,
305
+ ascending: bool = False,
306
+ fig: Optional[go.Figure] = None) -> go.Figure:
307
+ pd_dfs:Dict[str,pd.DataFrame]={}
308
+ for path in pathes:
309
+ pd_dfs[path]=self._obj
310
+
311
+
312
+ return plot_composite_treemap(pd_dfs=pd_dfs,
313
+ values=values,
314
+ title=title,
315
+ style=style,
316
+ color=color,
317
+ sort_by=sort_by,
318
+ ascending=ascending,
319
+ max_values=max_values)
320
+
297
321
 
298
322
  __all__ = ["validate_dataframe", "aplot_bubble", "aplot_timeserie", "aplot_table", "aplot_network", "aplot_network_components", "fplot_network",
299
- "plot_pivotbar", "fplot_treemap", "aplot_treemap", "plot_composite_bubble", "StyleTemplate", "DataFrameAccessor"]
323
+ "plot_pivotbar", "fplot_treemap", "aplot_treemap", "plot_composite_bubble","plot_composite_treemap", "StyleTemplate", "DataFrameAccessor"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MatplotLibAPI
3
- Version: 3.2.8
3
+ Version: 3.2.10
4
4
  Requires-Python: >=3.7
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -0,0 +1,14 @@
1
+ MatplotLibAPI/Bubble.py,sha256=ZtOTWGAnJ1zy7bjKQ3OF985R-iZHvZOo_rG1dZMbP-Q,5116
2
+ MatplotLibAPI/Composite.py,sha256=2t4AvmxbxRX2BumhXGSGkBBdo71uudWwW1HpsKML7lQ,7250
3
+ MatplotLibAPI/Network.py,sha256=zzizLBAMD-nV-1WGZTIoOQn3SVsvr9R8Ba2DTCyuTvA,18790
4
+ MatplotLibAPI/Pivot.py,sha256=Bo7ZpkxqoE75e8vpSsKIT5X2Q7lLdfAyy46ox1fARbc,7183
5
+ MatplotLibAPI/StyleTemplate.py,sha256=YtDsDIEYjpHqLuj1YXlmLUbBdxHfoq7ndQ1sG4WD1IA,10967
6
+ MatplotLibAPI/Table.py,sha256=p_nHXRiC6dneBSf0j5nx-hBijBSXd7NBLmdBicFUGqQ,2809
7
+ MatplotLibAPI/Timeserie.py,sha256=B03xjcBCgWVpkDQKvoyGtNjm6OLtCo1fINyXJrXeWM8,4952
8
+ MatplotLibAPI/Treemap.py,sha256=1WYHV9eaU4zcXrwTIScQvsGrfgiuYg-aAoeIhTZVPKw,3395
9
+ MatplotLibAPI/__init__.py,sha256=5a9TvLliMN0o-1V8Lw0Gj0JSQMXh8jTWxxgLcxIhLxU,13948
10
+ MatplotLibAPI-3.2.10.dist-info/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
11
+ MatplotLibAPI-3.2.10.dist-info/METADATA,sha256=E2YGsD_eO1AkCFS5kE3rmrUj0hP6AU5XawkzVhSgSlo,463
12
+ MatplotLibAPI-3.2.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
13
+ MatplotLibAPI-3.2.10.dist-info/top_level.txt,sha256=MrzbBjDEW48Vb6YhQIqpFYGOhHzQnEIM5Qy2xy2iqew,14
14
+ MatplotLibAPI-3.2.10.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- MatplotLibAPI/Bubble.py,sha256=ZtOTWGAnJ1zy7bjKQ3OF985R-iZHvZOo_rG1dZMbP-Q,5116
2
- MatplotLibAPI/Composite.py,sha256=YpC4VxYX4nMgiiV8ic734c_NGaCTdQCptT8bpMdTqCQ,4222
3
- MatplotLibAPI/Network.py,sha256=zzizLBAMD-nV-1WGZTIoOQn3SVsvr9R8Ba2DTCyuTvA,18790
4
- MatplotLibAPI/Pivot.py,sha256=Bo7ZpkxqoE75e8vpSsKIT5X2Q7lLdfAyy46ox1fARbc,7183
5
- MatplotLibAPI/StyleTemplate.py,sha256=va8_yXaun1RnjQUOEHGvsXJrKWHdzz4BhnY0CkROLW8,4599
6
- MatplotLibAPI/Table.py,sha256=p_nHXRiC6dneBSf0j5nx-hBijBSXd7NBLmdBicFUGqQ,2809
7
- MatplotLibAPI/Timeserie.py,sha256=B03xjcBCgWVpkDQKvoyGtNjm6OLtCo1fINyXJrXeWM8,4952
8
- MatplotLibAPI/Treemap.py,sha256=1WYHV9eaU4zcXrwTIScQvsGrfgiuYg-aAoeIhTZVPKw,3395
9
- MatplotLibAPI/__init__.py,sha256=-NgOIPG0P7G4pllESRsrOzcKgT0u-ZSE04AHRk-8Aas,12918
10
- MatplotLibAPI-3.2.8.dist-info/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
11
- MatplotLibAPI-3.2.8.dist-info/METADATA,sha256=X-bNBBQloDBC8Np3t6YsFWi3AjJ3AG_OOH9GdEJAudU,462
12
- MatplotLibAPI-3.2.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
13
- MatplotLibAPI-3.2.8.dist-info/top_level.txt,sha256=MrzbBjDEW48Vb6YhQIqpFYGOhHzQnEIM5Qy2xy2iqew,14
14
- MatplotLibAPI-3.2.8.dist-info/RECORD,,