newsworthycharts 1.62.0__py3-none-any.whl → 1.63.0__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.
- newsworthycharts/__init__.py +1 -1
- newsworthycharts/chart.py +29 -2
- newsworthycharts/lib/locator.py +4 -1
- newsworthycharts/lib/utils.py +8 -2
- newsworthycharts/serialchart.py +15 -6
- {newsworthycharts-1.62.0.dist-info → newsworthycharts-1.63.0.dist-info}/METADATA +12 -7
- {newsworthycharts-1.62.0.dist-info → newsworthycharts-1.63.0.dist-info}/RECORD +10 -10
- {newsworthycharts-1.62.0.dist-info → newsworthycharts-1.63.0.dist-info}/LICENSE.txt +0 -0
- {newsworthycharts-1.62.0.dist-info → newsworthycharts-1.63.0.dist-info}/WHEEL +0 -0
- {newsworthycharts-1.62.0.dist-info → newsworthycharts-1.63.0.dist-info}/top_level.txt +0 -0
newsworthycharts/__init__.py
CHANGED
newsworthycharts/chart.py
CHANGED
@@ -17,7 +17,8 @@ from matplotlib.font_manager import FontProperties
|
|
17
17
|
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
18
18
|
from matplotlib.figure import Figure
|
19
19
|
from matplotlib.ticker import FuncFormatter
|
20
|
-
from matplotlib.dates import DateFormatter, num2date
|
20
|
+
from matplotlib.dates import DateFormatter, num2date, YearLocator
|
21
|
+
|
21
22
|
from langcodes import standardize_tag
|
22
23
|
from PIL import Image
|
23
24
|
from babel import Locale
|
@@ -366,7 +367,10 @@ class Chart(object):
|
|
366
367
|
self.ax.plot([0], transform=self.ax.transAxes, **kwargs)
|
367
368
|
|
368
369
|
def _set_date_ticks(self, dates):
|
369
|
-
"""
|
370
|
+
"""
|
371
|
+
Set x ticks and formatters for chart types working on date series.
|
372
|
+
Todo: Unify location setting, to be able to support max_ticks everywhere.
|
373
|
+
"""
|
370
374
|
|
371
375
|
# Number of days on x axis (Matplotlib will use days as unit here)
|
372
376
|
xmin, xmax = to_date(self.data.x_points[0]), to_date(self.data.x_points[-1])
|
@@ -377,9 +381,31 @@ class Chart(object):
|
|
377
381
|
self.ax.set_xticks([x[0] for x in self.ticks])
|
378
382
|
self.ax.set_xticklabels([x[1] for x in self.ticks])
|
379
383
|
|
384
|
+
elif self.interval == "decennial":
|
385
|
+
# Get the intervall needed to stay below max_ticks
|
386
|
+
i = 1
|
387
|
+
while len(dates) / i > self.max_ticks:
|
388
|
+
i += 1
|
389
|
+
loc = YearLocator(10 * i)
|
390
|
+
# loc = get_best_locator(delta, len(dates), self.interval)
|
391
|
+
self.ax.xaxis.set_major_locator(loc)
|
392
|
+
|
393
|
+
formatter = Formatter(self._language)
|
394
|
+
|
395
|
+
def fmt(x, pos):
|
396
|
+
d = num2date(x).isoformat()[:10]
|
397
|
+
# 9 years later
|
398
|
+
d2 = str(int(d[:4]) + 9) + d[4:]
|
399
|
+
if len(self.data.x_points) > 7:
|
400
|
+
return formatter.date(d, "yy") + "–" + formatter.date(d2, "yy")
|
401
|
+
else:
|
402
|
+
return formatter.date(d, "y") + "–" + formatter.date(d2, "yy")
|
403
|
+
self.ax.xaxis.set_major_formatter(fmt)
|
404
|
+
|
380
405
|
elif delta.days > 500:
|
381
406
|
ticks = get_year_ticks(xmin, xmax, max_ticks=self.max_ticks)
|
382
407
|
self.ax.set_xticks(ticks)
|
408
|
+
|
383
409
|
self.ax.xaxis.set_major_formatter(DateFormatter('%Y'))
|
384
410
|
|
385
411
|
else:
|
@@ -667,6 +693,7 @@ class Chart(object):
|
|
667
693
|
'Creator': f"NWCharts {__version__}",
|
668
694
|
}
|
669
695
|
"""
|
696
|
+
|
670
697
|
self._fig.savefig(buf, **args) # , bbox_inches="tight")
|
671
698
|
buf.seek(0)
|
672
699
|
self._storage.save(key, buf, img_format, storage_options)
|
newsworthycharts/lib/locator.py
CHANGED
@@ -42,7 +42,10 @@ def get_best_locator(delta, points, interval=None):
|
|
42
42
|
trying to keep the x axis as clean as possible, while still including
|
43
43
|
enough clues for the reader to easily understand the graph.
|
44
44
|
"""
|
45
|
-
if
|
45
|
+
if interval == "decennial":
|
46
|
+
# Set one tick every 10 years
|
47
|
+
return YearLocator(10)
|
48
|
+
elif delta.days > 365 * 150:
|
46
49
|
return YearLocator(100)
|
47
50
|
elif delta.days > 365 * 45:
|
48
51
|
return YearLocator(20)
|
newsworthycharts/lib/utils.py
CHANGED
@@ -163,15 +163,21 @@ def outline(color="white", linewidth=3, **kwargs):
|
|
163
163
|
|
164
164
|
def guess_date_interval(data):
|
165
165
|
"""Return a probable interval, e.g. "montly", given current data."""
|
166
|
-
interval = "
|
166
|
+
interval = "decennial"
|
167
167
|
for serie in data:
|
168
168
|
dates = [to_date(x[0]) for x in serie]
|
169
169
|
years = [x.year for x in dates]
|
170
|
+
|
171
|
+
# Are there decades with more than one year?
|
172
|
+
if len(years) > len(set(years)):
|
173
|
+
interval = "yearly"
|
174
|
+
|
170
175
|
months = [x.month for x in dates]
|
171
176
|
yearmonths = [x.strftime("%Y-%m") for x in dates]
|
172
177
|
weeks = [str(x.year) + str(x.isocalendar()[1]) for x in dates]
|
178
|
+
|
173
179
|
if len(years) > len(set(years)):
|
174
|
-
# there
|
180
|
+
# Are there years with more than one point?
|
175
181
|
unique_months = sorted(list(set(months)))
|
176
182
|
if len(unique_months) == 4 \
|
177
183
|
and unique_months[0] + 3 == unique_months[1] \
|
newsworthycharts/serialchart.py
CHANGED
@@ -73,7 +73,8 @@ class SerialChart(Chart):
|
|
73
73
|
self._ymax = val
|
74
74
|
|
75
75
|
def _days_in(self, interval, d=None):
|
76
|
-
"""
|
76
|
+
"""
|
77
|
+
Return number of days in a given period. This is used to set bar widths, so approximate is fine.
|
77
78
|
|
78
79
|
If only interval is given, use a typical number of days.
|
79
80
|
>>>> _days_in(monthly)
|
@@ -83,6 +84,7 @@ class SerialChart(Chart):
|
|
83
84
|
"""
|
84
85
|
if d is None:
|
85
86
|
return {
|
87
|
+
'decennial': 3652,
|
86
88
|
'yearly': 365,
|
87
89
|
'quarterly': 91,
|
88
90
|
'monthly': 30,
|
@@ -109,6 +111,10 @@ class SerialChart(Chart):
|
|
109
111
|
return 7
|
110
112
|
elif interval == "daily":
|
111
113
|
return 1
|
114
|
+
elif interval == "decennial":
|
115
|
+
return (
|
116
|
+
(d + relativedelta(years=10)).replace(day=1, month=1) - d.replace(day=1, month=1)
|
117
|
+
).days
|
112
118
|
|
113
119
|
def _get_annotation_direction(self, index, values):
|
114
120
|
""" Given an index and series of values, provide the estimated best
|
@@ -284,11 +290,14 @@ class SerialChart(Chart):
|
|
284
290
|
|
285
291
|
# add highlight marker
|
286
292
|
if highlight_value:
|
287
|
-
self.ax.plot(
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
293
|
+
self.ax.plot(
|
294
|
+
highlight_date,
|
295
|
+
highlight_value,
|
296
|
+
c=color,
|
297
|
+
marker='o',
|
298
|
+
markersize=5,
|
299
|
+
zorder=zo,
|
300
|
+
)
|
292
301
|
|
293
302
|
elif self.type[i] == "bars":
|
294
303
|
# Put first series on top
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: newsworthycharts
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.63.0
|
4
4
|
Summary: Matplotlib wrapper to create charts and publish them on Amazon S3
|
5
5
|
Home-page: https://github.com/jplusplus/newsworthycharts
|
6
|
-
Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.
|
6
|
+
Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.63.0.tar.gz
|
7
7
|
Author: Jens Finnäs and Leo Wallentin, J++ Stockholm
|
8
8
|
Author-email: stockholm@jplusplus.org
|
9
9
|
License: MIT
|
@@ -18,11 +18,11 @@ Requires-Dist: PyYAML >=3
|
|
18
18
|
Requires-Dist: adjustText ==0.7.3
|
19
19
|
Requires-Dist: numpy >2
|
20
20
|
Requires-Dist: python-dateutil <3,>=2
|
21
|
-
Requires-Dist: Pillow ==
|
21
|
+
Requires-Dist: Pillow ==11.0.0
|
22
22
|
Requires-Dist: requests >=2.22
|
23
23
|
Requires-Dist: matplotlib-label-lines ==0.5.1
|
24
24
|
Requires-Dist: geopandas >=1
|
25
|
-
Requires-Dist: mapclassify ==2.
|
25
|
+
Requires-Dist: mapclassify ==2.8.1
|
26
26
|
Requires-Dist: puremagic >=1
|
27
27
|
|
28
28
|
This module contains methods for producing graphs and publishing them on Amazon S3, or in the location of your choice.
|
@@ -154,13 +154,13 @@ These settings are available for all chart types:
|
|
154
154
|
|
155
155
|
**SerialChart**
|
156
156
|
|
157
|
-
- type = 'line' # line|
|
157
|
+
- type = 'line' # line|bars
|
158
158
|
- bar_width = 0.9 # percent of data point width
|
159
159
|
- allow_broken_y_axis = True|False # default depends on chart type
|
160
160
|
- baseline = 0 # The “zero” line. Useful for plotting deviations, e.g. temperatures above/below mean
|
161
161
|
- baseline_annotation = None # A label for the baseline
|
162
162
|
- line_width = None # To override style settings
|
163
|
-
- max_ticks = 10 # Maximum number of ticks on the x axis
|
163
|
+
- max_ticks = 10 # Maximum number of ticks on the x axis. *Only used with yearly|decennial data* (this is yet to be fixed)
|
164
164
|
- ticks = None # Custom ticks on the x axis, as a list of lists or tuples: `[(2013-01-01, "-13"), (2014-01-01, "-14"), (2015-01-01, "-15")]`
|
165
165
|
- ymin = None # Minimum value on y axis. If None, it will be calculated from data
|
166
166
|
- ymax = None # Maximum value on y axis. If None, it will be calculated from data
|
@@ -248,11 +248,16 @@ Roadmap
|
|
248
248
|
- Remove custom charts (add missing api interfaces to Chart class instead)
|
249
249
|
- Remove DataWrapper class (out-of-scope)
|
250
250
|
- Custom month locator with equal-width month bars
|
251
|
-
- Add color-ramp choropleth maps, as an alternative to binning
|
252
251
|
|
253
252
|
Changelog
|
254
253
|
---------
|
255
254
|
|
255
|
+
- 1.63.0
|
256
|
+
|
257
|
+
- Added `interval: decennial` to SerialChart. Will be autodetected if all data points are 10 years apart.
|
258
|
+
- Pillow==11.0.0
|
259
|
+
- mapclassify==2.8.1
|
260
|
+
|
256
261
|
- 1.62.0
|
257
262
|
|
258
263
|
- max_ticks default is now 10 in SerialChart and 7 in ScatterPlot
|
@@ -1,14 +1,14 @@
|
|
1
|
-
newsworthycharts/__init__.py,sha256=
|
1
|
+
newsworthycharts/__init__.py,sha256=iyEaSC-FB3CheUeksBH1o0BZMMCGczVcLniWDXND5Us,1160
|
2
2
|
newsworthycharts/bubblemap.py,sha256=nkocWmpiFgfjEuJGAsthjY5X7Q56jXWsZHUGXw4PwgE,2587
|
3
3
|
newsworthycharts/categoricalchart.py,sha256=LwOZ3VbNy9vzvoK0s77AkbfMt4CXVDSAhnsnBInUIrE,14764
|
4
|
-
newsworthycharts/chart.py,sha256=
|
4
|
+
newsworthycharts/chart.py,sha256=e118gGQbFpRJZl3SWLhVCBatclG80eFdojrxJn8td5g,31664
|
5
5
|
newsworthycharts/choroplethmap.py,sha256=bCLf4kcchp1C2djg5AxcOM8BdbaMj0xg7UHrZsDafhI,8013
|
6
6
|
newsworthycharts/datawrapper.py,sha256=RRkAVTpfP4updKxUIBaSmKuBi2RUVPaBRF8HDQhlGGA,11250
|
7
7
|
newsworthycharts/map.py,sha256=c409jEO4L8Yr780sJRC0RchR44roAlgOUDAkuk1SfRg,6057
|
8
8
|
newsworthycharts/rangeplot.py,sha256=NE1W9TnmlpK6T3RvBJOU3nd73EXqkj17OY9i5zlw_cQ,8366
|
9
9
|
newsworthycharts/scatterplot.py,sha256=l2w2JkA_4WzxQG9XG1Pn62IlJOdCMm1VemMiZL0rEfU,4959
|
10
10
|
newsworthycharts/seasonalchart.py,sha256=rr55yqJUkaYDR9Ik98jes6574oY1U8t8LwoLE3gClW4,1967
|
11
|
-
newsworthycharts/serialchart.py,sha256=
|
11
|
+
newsworthycharts/serialchart.py,sha256=WrCWyDDRkXBXSqNyIhoBnm7A5RR2_wlluFPYirq_Snw,27686
|
12
12
|
newsworthycharts/storage.py,sha256=myERhlpvXyExXxUByBq9eW1bWkCyfH9SwTZbsWSyy3Q,4301
|
13
13
|
newsworthycharts/stripechart.py,sha256=9B6PX2MyLuKNQ8W0OGdKbP0-U32kju0K_NHHwwz_J68,1547
|
14
14
|
newsworthycharts/custom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -19,17 +19,17 @@ newsworthycharts/lib/colors.py,sha256=U04TDkvoMQkcldRFXfnwyLOTwq1SWW2se-Ad-DNcw9
|
|
19
19
|
newsworthycharts/lib/datalist.py,sha256=fsO_esZBt4Aw_4n_l2LuswAYArbM-8Z8G9DAXo1oVZU,5376
|
20
20
|
newsworthycharts/lib/formatter.py,sha256=GNH43hE0bC17OgiV8LYH3YUrEhm7OJh9XzfSV4HVtHo,4838
|
21
21
|
newsworthycharts/lib/geography.py,sha256=K0_teFmuPJwXX7Py-amJB_1YY5_gL2kBYhz1LrRCyTg,584
|
22
|
-
newsworthycharts/lib/locator.py,sha256=
|
22
|
+
newsworthycharts/lib/locator.py,sha256=rJHdgiA0LASRzdLINhTeU5zOoq1TCMgge4KOBWSagnM,3041
|
23
23
|
newsworthycharts/lib/mimetypes.py,sha256=bL9HtVWbn2Of39LcBt4u4yelkr4bGZiyebq3OfLnfFY,237
|
24
|
-
newsworthycharts/lib/utils.py,sha256=
|
24
|
+
newsworthycharts/lib/utils.py,sha256=Io_yBHxUDTXw-9GvsizdSXnYvE_7ZtDKiWpLTAXpHfA,7171
|
25
25
|
newsworthycharts/maps/se-4.gpkg,sha256=oWw5j7FPVpI0ig67jNDim8qSn5SG8rcHp0014-uTKZM,290816
|
26
26
|
newsworthycharts/maps/se-7.gpkg,sha256=Vmvqudq_ZtgV0sd6TY6kuk7vzqmYZCJmaxtsJ87q2a8,331776
|
27
27
|
newsworthycharts/rc/newsworthy,sha256=vbYTav1w3DmB5tpaaV7Xl5q7TQJsc9eou6pLCoWc2vs,1589
|
28
28
|
newsworthycharts/translations/datawrapper_regions.csv,sha256=fzZcQRX6RFMlNNP8mpgfYNdR3Y0QAlQxDXk8FXTaWWI,9214
|
29
29
|
newsworthycharts/translations/regions.py,sha256=Nv1McQjggD4S3JRu82rDMTG3pqUVR13E5-FBpSYbm98,239
|
30
30
|
newsworthycharts/translations/se_municipalities.csv,sha256=br_mm-IvzQtj_W55_ATREhJ97jWnCweBFlDAVY2EBxA,7098
|
31
|
-
newsworthycharts-1.
|
32
|
-
newsworthycharts-1.
|
33
|
-
newsworthycharts-1.
|
34
|
-
newsworthycharts-1.
|
35
|
-
newsworthycharts-1.
|
31
|
+
newsworthycharts-1.63.0.dist-info/LICENSE.txt,sha256=Sq6kGICrehbhC_FolNdXf0djKjTpv3YqjFCIYsxdQN4,1069
|
32
|
+
newsworthycharts-1.63.0.dist-info/METADATA,sha256=25lu-t46S5NLSLrKSyy5QdMSPgqLmcHtmyEdYhvRRCU,29278
|
33
|
+
newsworthycharts-1.63.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
34
|
+
newsworthycharts-1.63.0.dist-info/top_level.txt,sha256=dn_kzIj8UgUCMsh1PHdVEQJHVGSsN7Z8YJF-8xXa8n0,17
|
35
|
+
newsworthycharts-1.63.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|