hiveplotlib 0.26.0rc1__tar.gz → 0.26.2__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.
- {hiveplotlib-0.26.0rc1/src/hiveplotlib.egg-info → hiveplotlib-0.26.2}/PKG-INFO +6 -6
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/pyproject.toml +46 -9
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/__init__.py +3 -3
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/international_trade.py +3 -2
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/edges.py +2 -4
- hiveplotlib-0.26.2/src/hiveplotlib/exceptions/__init__.py +6 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/hiveplot.py +87 -64
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/node.py +6 -5
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/p2cp.py +3 -2
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/base.py +4 -4
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/bokeh.py +3 -4
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/datashader.py +3 -2
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/holoviews.py +12 -10
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/input_checks.py +4 -6
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/matplotlib.py +1 -1
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/plotly.py +2 -3
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2/src/hiveplotlib.egg-info}/PKG-INFO +6 -6
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib.egg-info/requires.txt +4 -4
- hiveplotlib-0.26.0rc1/src/hiveplotlib/exceptions/__init__.py +0 -6
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/LICENSE +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/MANIFEST.in +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/README.md +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/setup.cfg +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/setup.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/__init__.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/axis.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/converters.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/toy_hive_plots.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/toy_p2cps.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/trade_data_harvard_growth_lab/international_exports_2019_8112.csv +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/trade_data_harvard_growth_lab/international_exports_metadata_2019_8112.json +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/exceptions/hive_plot.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/exceptions/node.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/utils.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/viz/__init__.py +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib.egg-info/SOURCES.txt +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib.egg-info/dependency_links.txt +0 -0
- {hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hiveplotlib
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.2
|
|
4
4
|
Summary: Visualize Network Data with Hive Plots
|
|
5
5
|
Author-email: Gary Koplik <gary.koplik@geomdata.com>
|
|
6
6
|
License: Copyright (c) 2020 - 2024, Geometric Data Analytics, Inc.
|
|
@@ -34,7 +34,7 @@ License: Copyright (c) 2020 - 2024, Geometric Data Analytics, Inc.
|
|
|
34
34
|
|
|
35
35
|
Project-URL: Documentation, https://hiveplotlib.readthedocs.io/stable/
|
|
36
36
|
Project-URL: Source, https://gitlab.com/geomdata/hiveplotlib
|
|
37
|
-
Requires-Python: >=3.
|
|
37
|
+
Requires-Python: >=3.10
|
|
38
38
|
Description-Content-Type: text/markdown
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: matplotlib
|
|
@@ -48,13 +48,13 @@ Requires-Dist: datashader; extra == "datashader"
|
|
|
48
48
|
Requires-Dist: numba>0.54.0; extra == "datashader"
|
|
49
49
|
Requires-Dist: seaborn; extra == "datashader"
|
|
50
50
|
Provides-Extra: dev
|
|
51
|
-
Requires-Dist: bokeh
|
|
51
|
+
Requires-Dist: bokeh; extra == "dev"
|
|
52
52
|
Requires-Dist: cartopy; extra == "dev"
|
|
53
53
|
Requires-Dist: dask[dataframe]; extra == "dev"
|
|
54
54
|
Requires-Dist: datashader; extra == "dev"
|
|
55
55
|
Requires-Dist: flexitext; extra == "dev"
|
|
56
56
|
Requires-Dist: geopandas; extra == "dev"
|
|
57
|
-
Requires-Dist: holoviews
|
|
57
|
+
Requires-Dist: holoviews; extra == "dev"
|
|
58
58
|
Requires-Dist: jupyter; extra == "dev"
|
|
59
59
|
Requires-Dist: networkx; extra == "dev"
|
|
60
60
|
Requires-Dist: numba>0.54.0; extra == "dev"
|
|
@@ -70,8 +70,8 @@ Requires-Dist: sphinx; extra == "docs"
|
|
|
70
70
|
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
71
71
|
Requires-Dist: toml; extra == "docs"
|
|
72
72
|
Provides-Extra: holoviews
|
|
73
|
-
Requires-Dist: bokeh
|
|
74
|
-
Requires-Dist: holoviews
|
|
73
|
+
Requires-Dist: bokeh; extra == "holoviews"
|
|
74
|
+
Requires-Dist: holoviews; extra == "holoviews"
|
|
75
75
|
Requires-Dist: numba>0.54.0; extra == "holoviews"
|
|
76
76
|
Provides-Extra: networkx
|
|
77
77
|
Requires-Dist: networkx; extra == "networkx"
|
|
@@ -6,8 +6,8 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "hiveplotlib"
|
|
9
|
-
requires-python = ">=3.
|
|
10
|
-
version = "0.26.
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
version = "0.26.2"
|
|
11
11
|
authors = [
|
|
12
12
|
{name="Gary Koplik", email="gary.koplik@geomdata.com"}
|
|
13
13
|
]
|
|
@@ -38,13 +38,13 @@ datashader = [
|
|
|
38
38
|
|
|
39
39
|
# developer dependencies
|
|
40
40
|
dev = [
|
|
41
|
-
"bokeh
|
|
41
|
+
"bokeh",
|
|
42
42
|
"cartopy",
|
|
43
43
|
"dask[dataframe]", # https://github.com/holoviz/datashader/issues/1319
|
|
44
44
|
"datashader",
|
|
45
45
|
"flexitext",
|
|
46
46
|
"geopandas",
|
|
47
|
-
"holoviews
|
|
47
|
+
"holoviews",
|
|
48
48
|
"jupyter",
|
|
49
49
|
"networkx",
|
|
50
50
|
"numba>0.54.0", # https://github.com/numba/numba/issues/9708
|
|
@@ -65,8 +65,8 @@ docs = [
|
|
|
65
65
|
]
|
|
66
66
|
|
|
67
67
|
holoviews = [
|
|
68
|
-
"bokeh
|
|
69
|
-
"holoviews
|
|
68
|
+
"bokeh",
|
|
69
|
+
"holoviews",
|
|
70
70
|
"numba>0.54.0", # https://github.com/numba/numba/issues/9708
|
|
71
71
|
]
|
|
72
72
|
|
|
@@ -121,32 +121,69 @@ extend-ignore = [
|
|
|
121
121
|
"D203", # don't require blank line before class docstring.
|
|
122
122
|
"D212", # require docstring text starts on the next line after the triple quotes.
|
|
123
123
|
"E203", # https://black.readthedocs.io/en/stable/faq.html#why-are-flake8-s-e203-and-w503-violated
|
|
124
|
-
"PD901", # generic `df` name for pandas dataframes will be tolerated
|
|
125
|
-
"B905", # this is a python 3.10 convention, drop ignore when we drop 3.9 support
|
|
126
124
|
]
|
|
127
125
|
|
|
126
|
+
|
|
127
|
+
|
|
128
128
|
extend-select = [
|
|
129
129
|
"A", # use flake8-builtins (check if variable name shadows python builtin names)
|
|
130
130
|
"ANN", # use flake8-annotations (checks type annotations)
|
|
131
131
|
"ARG", # use flake8-unused-arguments (checks for unused arguments)
|
|
132
132
|
"B", # use flake8-bugbear (nice for cleaner code)
|
|
133
|
-
"C4", # use flake8-comprehensions (remove unnecessary literals, generators, lists, etc.)
|
|
133
|
+
"C4", # use flake8-comprehensions (remove unnecessary literals, generators, lists, etc.)
|
|
134
134
|
"D", # use pydoc style rules
|
|
135
|
+
# "DOC", # usepydoclinter (additional docstring checks) (commented out because in preview at last change 12/31/25)
|
|
135
136
|
"E", # use pycodestyle warnings
|
|
137
|
+
"EM", # use flake8-errmsg (improved error messages)
|
|
138
|
+
"ERA", # use flake8-eradicate (checks for commented out code)
|
|
139
|
+
"F", # use pyflakes rules
|
|
136
140
|
"I", # use isort rules
|
|
137
141
|
"ICN", # use flake-import-conventions (checks that imports use standard names)
|
|
142
|
+
"INP", # use flake8-no-pep420 (disallow implicit namespace packages)
|
|
143
|
+
"ISC", # use flake8-implicit-str-concat (checks for implicit string concatenation),
|
|
138
144
|
"N", # use pep8 naming
|
|
139
145
|
"NPY", # numpy-specific rules
|
|
140
146
|
"PERF", # linter focused on avoiding performance anti-patterns
|
|
141
147
|
"PIE", # use flake8-pie (some misc additional linting)
|
|
142
148
|
"PD", # write pandas code more in line with pd recommendations
|
|
143
149
|
"PT", # use flake8-pytest-style (linting specifically for pytest)
|
|
150
|
+
"PTH", # use flake8-pathlib (encourages use of pathlib over os.path)
|
|
151
|
+
"Q", # use flake8-quotes (enforce consistent quote style)
|
|
144
152
|
"RET", # use flake8-return (linting on return / raise)
|
|
153
|
+
"RSE", # use flake8-raise (checks for unnecssary parentheses in raised exceptions)
|
|
154
|
+
"RUF", # ruff's own linting rules
|
|
145
155
|
"SIM", # use flake8-simplify (helps simplify logic in code)
|
|
156
|
+
"T20", # use flake8-print (to prevent print statements)
|
|
157
|
+
"TC", # use flake8-type-checking (type checking imports)
|
|
146
158
|
"TID", # use flake8-tidy-imports (to prevent relative imports)
|
|
147
159
|
"W", # use pycodestyle warnings
|
|
148
160
|
]
|
|
149
161
|
|
|
162
|
+
[tool.ruff.lint.per-file-ignores]
|
|
163
|
+
|
|
164
|
+
".gitlab/*" = [
|
|
165
|
+
"INP001", # don't require __init__.py in folder
|
|
166
|
+
"T201", # allow print statements
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
"docs/*" = [
|
|
170
|
+
"INP001", # don't require __init__.py in folder
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
"examples/*" = [
|
|
174
|
+
"T201", # allow print statements
|
|
175
|
+
"T203", # allow pprint statements
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
"runners/*" = [
|
|
179
|
+
"INP001", # don't require __init__.py in runners
|
|
180
|
+
"T201", # allow print statements
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
"tests/*" = [
|
|
184
|
+
"ERA001", # allow commented out code in tests
|
|
185
|
+
]
|
|
186
|
+
|
|
150
187
|
[tool.ruff.lint.pydocstyle]
|
|
151
188
|
convention = "pep257"
|
|
152
189
|
|
|
@@ -16,6 +16,6 @@ For Polar Parallel Coordinates Plots (P2CPs), many datasets are available throug
|
|
|
16
16
|
`scikit-learn <https://scikit-learn.org/stable/datasets.html>`_.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
from hiveplotlib.datasets.international_trade import * # noqa:
|
|
20
|
-
from hiveplotlib.datasets.toy_hive_plots import * # noqa:
|
|
21
|
-
from hiveplotlib.datasets.toy_p2cps import * # noqa:
|
|
19
|
+
from hiveplotlib.datasets.international_trade import * # noqa: F403
|
|
20
|
+
from hiveplotlib.datasets.toy_hive_plots import * # noqa: F403
|
|
21
|
+
from hiveplotlib.datasets.toy_p2cps import * # noqa: F403
|
{hiveplotlib-0.26.0rc1 → hiveplotlib-0.26.2}/src/hiveplotlib/datasets/international_trade.py
RENAMED
|
@@ -62,15 +62,16 @@ def international_trade_data(
|
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
if not (data_path.exists() and metadata_path.exists()):
|
|
65
|
-
|
|
65
|
+
msg = (
|
|
66
66
|
"Could not find data and / or metadata under specified `path`. If you specified your own path, double "
|
|
67
67
|
"check that the path is correct. Your file names should be "
|
|
68
68
|
"If you are using `hiveplotlib` supported data, note that only the following `year`, "
|
|
69
69
|
f"`hs29_code` values are supported:\n{hiveplotlib_supported_values}"
|
|
70
70
|
)
|
|
71
|
+
raise ValueError(msg)
|
|
71
72
|
|
|
72
73
|
data = pd.read_csv(data_path)
|
|
73
|
-
with open(
|
|
74
|
+
with Path(metadata_path).open("r") as openfile:
|
|
74
75
|
metadata = json.load(openfile)
|
|
75
76
|
|
|
76
77
|
return data, metadata
|
|
@@ -83,9 +83,7 @@ class Edges:
|
|
|
83
83
|
return "hiveplotlib.Edges of 0 edges."
|
|
84
84
|
|
|
85
85
|
if len(kws) == 1:
|
|
86
|
-
return (
|
|
87
|
-
f"hiveplotlib.Edges of {list(self._data.values())[0].shape[0]} edges."
|
|
88
|
-
)
|
|
86
|
+
return f"hiveplotlib.Edges of {next(iter(self._data.values())).shape[0]} edges."
|
|
89
87
|
|
|
90
88
|
sizes = [self._data[kw].shape[0] for kw in kws]
|
|
91
89
|
return f"hiveplotlib.Edges of {sum(sizes)} edges across {len(kws)} tags."
|
|
@@ -181,7 +179,7 @@ class Edges:
|
|
|
181
179
|
corresponds to the tag assigned for each set of edges.
|
|
182
180
|
"""
|
|
183
181
|
if len(self._data) == 1:
|
|
184
|
-
return
|
|
182
|
+
return next(iter(self._data.values()))
|
|
185
183
|
return self._data
|
|
186
184
|
|
|
187
185
|
def add_edges(
|
|
@@ -247,11 +247,12 @@ class BaseHivePlot:
|
|
|
247
247
|
:return: ``None``.
|
|
248
248
|
"""
|
|
249
249
|
if unique_ids is not None:
|
|
250
|
-
|
|
250
|
+
msg = (
|
|
251
251
|
"As of hiveplotlib>=0.26.0, `place_nodes_on_axis() now takes node subsets via the `node_df` parameter, "
|
|
252
252
|
"with support dropped for `unique_ids`. Node dataframe subsetting should be performed on the hive "
|
|
253
253
|
"plot's node dataframe, stored under the hive plot's ``nodes.data`` attribute."
|
|
254
254
|
)
|
|
255
|
+
raise TypeError(msg)
|
|
255
256
|
# ToDo: allow rescaling option before thresholding on min and max values (e.g. put in log scale)
|
|
256
257
|
|
|
257
258
|
if node_df is None:
|
|
@@ -406,7 +407,8 @@ class BaseHivePlot:
|
|
|
406
407
|
self.edges.relevant_edges[axis_id_1].setdefault(axis_id_2, {})
|
|
407
408
|
self.edges.relevant_edges[axis_id_1][axis_id_2][tag] = {}
|
|
408
409
|
else:
|
|
409
|
-
|
|
410
|
+
msg = "Key to delete not found. No edge data deleted."
|
|
411
|
+
raise ValueError(msg)
|
|
410
412
|
if a2_to_a1:
|
|
411
413
|
if tag in self.hive_plot_edges[axis_id_2][axis_id_1]:
|
|
412
414
|
del self.hive_plot_edges[axis_id_2][axis_id_1][tag]
|
|
@@ -415,7 +417,8 @@ class BaseHivePlot:
|
|
|
415
417
|
self.edges.relevant_edges[axis_id_2].setdefault(axis_id_1, {})
|
|
416
418
|
self.edges.relevant_edges[axis_id_2][axis_id_1][tag] = {}
|
|
417
419
|
else:
|
|
418
|
-
|
|
420
|
+
msg = "Key to delete not found. No edge data deleted."
|
|
421
|
+
raise ValueError(msg)
|
|
419
422
|
|
|
420
423
|
# just to and from axes => kill all the connections between the two axes
|
|
421
424
|
elif axis_id_2 is not None and axis_id_1 is not None:
|
|
@@ -447,9 +450,8 @@ class BaseHivePlot:
|
|
|
447
450
|
self.edges.relevant_edges[a0][axis_id_1] = {}
|
|
448
451
|
|
|
449
452
|
else:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
)
|
|
453
|
+
msg = "See the docstring for ``BaseHivePlot.reset_edges()`` for more on supported uses."
|
|
454
|
+
raise NotImplementedError(msg)
|
|
453
455
|
|
|
454
456
|
def __check_unique_edge_subset_tag(
|
|
455
457
|
self, tag: Hashable, from_axis_id: Hashable, to_axis_id: Hashable
|
|
@@ -465,10 +467,11 @@ class BaseHivePlot:
|
|
|
465
467
|
:return: ``None``.
|
|
466
468
|
"""
|
|
467
469
|
if tag in self.hive_plot_edges[from_axis_id][to_axis_id]:
|
|
468
|
-
|
|
470
|
+
msg = (
|
|
469
471
|
f"Non-unique tag ({tag}) specified from {from_axis_id} to {to_axis_id}.\n"
|
|
470
472
|
"Please provide edge subset with a new unique tag."
|
|
471
473
|
)
|
|
474
|
+
raise ValueError(msg)
|
|
472
475
|
|
|
473
476
|
def _find_unique_tag(
|
|
474
477
|
self, from_axis_id: Hashable, to_axis_id: Hashable, bidirectional: bool = False
|
|
@@ -623,7 +626,8 @@ class BaseHivePlot:
|
|
|
623
626
|
if a1_to_a2 and a2_to_a1 and tag is None:
|
|
624
627
|
bidirectional = True
|
|
625
628
|
elif not a1_to_a2 and not a2_to_a1:
|
|
626
|
-
|
|
629
|
+
msg = "One of `a1_to_a2` or `a2_to_a1` must be true."
|
|
630
|
+
raise ValueError(msg)
|
|
627
631
|
else:
|
|
628
632
|
bidirectional = False
|
|
629
633
|
# axis 1 to axis 2
|
|
@@ -762,9 +766,9 @@ class BaseHivePlot:
|
|
|
762
766
|
"No edges specified to construct. Be sure to run the `add_edge_ids()` method first."
|
|
763
767
|
)
|
|
764
768
|
|
|
765
|
-
a1_to_a2_tag =
|
|
766
|
-
|
|
767
|
-
|
|
769
|
+
a1_to_a2_tag = next(
|
|
770
|
+
iter(self.hive_plot_edges[axis_id_1][axis_id_2].keys())
|
|
771
|
+
)
|
|
768
772
|
|
|
769
773
|
if len(list(self.hive_plot_edges[axis_id_1][axis_id_2].keys())) > 1:
|
|
770
774
|
a1_to_a2_failure = True
|
|
@@ -776,33 +780,36 @@ class BaseHivePlot:
|
|
|
776
780
|
"No edges specified to construct. Be sure to run the `add_edge_ids()` method first."
|
|
777
781
|
)
|
|
778
782
|
|
|
779
|
-
a2_to_a1_tag =
|
|
780
|
-
|
|
781
|
-
|
|
783
|
+
a2_to_a1_tag = next(
|
|
784
|
+
iter(self.hive_plot_edges[axis_id_2][axis_id_1].keys())
|
|
785
|
+
)
|
|
782
786
|
|
|
783
787
|
if len(list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())) > 1:
|
|
784
788
|
a2_to_a1_failure = True
|
|
785
789
|
|
|
786
790
|
if a1_to_a2_failure and a2_to_a1_failure:
|
|
787
|
-
|
|
791
|
+
msg = (
|
|
788
792
|
"Must specify precise `tag` to handle both `a1_to_a2=True` and `a2_to_a1=True` here. "
|
|
789
793
|
"The current tags for the specified axes are:\n"
|
|
790
|
-
f"{axis_id_2} -> {axis_id_1: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}
|
|
791
|
-
f"{axis_id_2} -> {axis_id_1: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}
|
|
794
|
+
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}\n"
|
|
795
|
+
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}"
|
|
792
796
|
)
|
|
797
|
+
raise ValueError(msg)
|
|
793
798
|
|
|
794
799
|
if a1_to_a2_failure:
|
|
795
|
-
|
|
800
|
+
msg = (
|
|
796
801
|
"Must specify precise `tag` to handle `a1_to_a2=True` here. "
|
|
797
802
|
"The current tags for the specified axes are:\n"
|
|
798
|
-
f"{axis_id_1} -> {axis_id_2: {list(self.hive_plot_edges[axis_id_1][axis_id_2].keys())}
|
|
803
|
+
f"{axis_id_1} -> {axis_id_2}: {list(self.hive_plot_edges[axis_id_1][axis_id_2].keys())}"
|
|
799
804
|
)
|
|
805
|
+
raise ValueError(msg)
|
|
800
806
|
if a2_to_a1_failure:
|
|
801
|
-
|
|
807
|
+
msg = (
|
|
802
808
|
"Must specify precise `tag` to handle `a2_to_a1=True` here. "
|
|
803
809
|
"The current tags for the specified axes are:\n"
|
|
804
|
-
f"{axis_id_2} -> {axis_id_1: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}
|
|
810
|
+
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}"
|
|
805
811
|
)
|
|
812
|
+
raise ValueError(msg)
|
|
806
813
|
|
|
807
814
|
else:
|
|
808
815
|
a1_to_a2_tag = tag
|
|
@@ -817,10 +824,11 @@ class BaseHivePlot:
|
|
|
817
824
|
all_connections.append(temp_connections)
|
|
818
825
|
direction.append("a1_to_a2")
|
|
819
826
|
except KeyError as ke:
|
|
820
|
-
|
|
827
|
+
msg = (
|
|
821
828
|
f"`self.edges[{axis_id_1}][{axis_id_2}][{a1_to_a2_tag}]['ids']` does not appear to exist. "
|
|
822
829
|
"It is expected you have run `self.add_edge_ids()` first for the two axes of interest."
|
|
823
|
-
)
|
|
830
|
+
)
|
|
831
|
+
raise KeyError(msg) from ke
|
|
824
832
|
if a2_to_a1:
|
|
825
833
|
try:
|
|
826
834
|
ids = self.hive_plot_edges[axis_id_2][axis_id_1][a2_to_a1_tag]["ids"]
|
|
@@ -828,17 +836,20 @@ class BaseHivePlot:
|
|
|
828
836
|
all_connections.append(temp_connections)
|
|
829
837
|
direction.append("a2_to_a1")
|
|
830
838
|
except KeyError as ke:
|
|
831
|
-
|
|
839
|
+
msg = (
|
|
832
840
|
f"`self.edges[{axis_id_2}][{axis_id_1}][{a2_to_a1_tag}]['ids']` does not appear to exist. "
|
|
833
841
|
"It is expected you have run `self.add_edge_ids()` first for the two axes of interest."
|
|
834
|
-
)
|
|
842
|
+
)
|
|
843
|
+
raise KeyError(msg) from ke
|
|
835
844
|
|
|
836
845
|
if len(all_connections) == 0:
|
|
837
|
-
|
|
846
|
+
msg = "One of `a1_to_a2` or `a2_to_a1` must be true."
|
|
847
|
+
raise ValueError(msg)
|
|
838
848
|
|
|
839
849
|
for connections, edge_direction in zip(
|
|
840
850
|
all_connections,
|
|
841
851
|
direction,
|
|
852
|
+
strict=True,
|
|
842
853
|
):
|
|
843
854
|
# left join the flattened start and stop values array with the cartesian and polar node locations
|
|
844
855
|
# Note: sorting behavior is not cooperating, so needed a trivial np.arange to re-sort at end
|
|
@@ -1113,9 +1124,9 @@ class BaseHivePlot:
|
|
|
1113
1124
|
a1_to_a2 = False
|
|
1114
1125
|
|
|
1115
1126
|
else:
|
|
1116
|
-
a1_to_a2_tag =
|
|
1117
|
-
self.hive_plot_edges[axis_id_1][axis_id_2].keys()
|
|
1118
|
-
)
|
|
1127
|
+
a1_to_a2_tag = next(
|
|
1128
|
+
iter(self.hive_plot_edges[axis_id_1][axis_id_2].keys())
|
|
1129
|
+
)
|
|
1119
1130
|
|
|
1120
1131
|
if (
|
|
1121
1132
|
len(list(self.hive_plot_edges[axis_id_1][axis_id_2].keys()))
|
|
@@ -1166,9 +1177,9 @@ class BaseHivePlot:
|
|
|
1166
1177
|
a2_to_a1 = False
|
|
1167
1178
|
|
|
1168
1179
|
else:
|
|
1169
|
-
a2_to_a1_tag =
|
|
1170
|
-
self.hive_plot_edges[axis_id_2][axis_id_1].keys()
|
|
1171
|
-
)
|
|
1180
|
+
a2_to_a1_tag = next(
|
|
1181
|
+
iter(self.hive_plot_edges[axis_id_2][axis_id_1].keys())
|
|
1182
|
+
)
|
|
1172
1183
|
|
|
1173
1184
|
if (
|
|
1174
1185
|
len(list(self.hive_plot_edges[axis_id_2][axis_id_1].keys()))
|
|
@@ -1190,24 +1201,27 @@ class BaseHivePlot:
|
|
|
1190
1201
|
a2_to_a1 = False
|
|
1191
1202
|
|
|
1192
1203
|
if a1_to_a2_failure and a2_to_a1_failure:
|
|
1193
|
-
|
|
1204
|
+
msg = (
|
|
1194
1205
|
"Must specify precise `tag` to handle both `a1_to_a2=True` and `a2_to_a1=True` here. "
|
|
1195
1206
|
"The current tags for the specified axes are:\n"
|
|
1196
1207
|
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}\n"
|
|
1197
1208
|
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}"
|
|
1198
1209
|
)
|
|
1210
|
+
raise ValueError(msg)
|
|
1199
1211
|
if a1_to_a2_failure:
|
|
1200
|
-
|
|
1212
|
+
msg = (
|
|
1201
1213
|
"Must specify precise `tag` to handle `a1_to_a2=True` here. "
|
|
1202
1214
|
"The current tags for the specified axes are:\n"
|
|
1203
1215
|
f"{axis_id_1} -> {axis_id_2}: {list(self.hive_plot_edges[axis_id_1][axis_id_2].keys())}"
|
|
1204
1216
|
)
|
|
1217
|
+
raise ValueError(msg)
|
|
1205
1218
|
if a2_to_a1_failure:
|
|
1206
|
-
|
|
1219
|
+
msg = (
|
|
1207
1220
|
"Must specify precise `tag` to handle `a2_to_a1=True` here. "
|
|
1208
1221
|
"The current tags for the specified axes are:\n"
|
|
1209
1222
|
f"{axis_id_2} -> {axis_id_1}: {list(self.hive_plot_edges[axis_id_2][axis_id_1].keys())}"
|
|
1210
1223
|
)
|
|
1224
|
+
raise ValueError(msg)
|
|
1211
1225
|
|
|
1212
1226
|
else:
|
|
1213
1227
|
a1_to_a2_tag = tag
|
|
@@ -1219,6 +1233,7 @@ class BaseHivePlot:
|
|
|
1219
1233
|
[a1_to_a2, a2_to_a1],
|
|
1220
1234
|
[[axis_id_1, axis_id_2], [axis_id_2, axis_id_1]],
|
|
1221
1235
|
[a1_to_a2_tag, a2_to_a1_tag],
|
|
1236
|
+
strict=True,
|
|
1222
1237
|
):
|
|
1223
1238
|
if direction:
|
|
1224
1239
|
if axis_ids[0] not in self.hive_plot_edges:
|
|
@@ -1241,7 +1256,7 @@ class BaseHivePlot:
|
|
|
1241
1256
|
axes.append([axis_ids[0], axis_ids[1]])
|
|
1242
1257
|
tags.append(t)
|
|
1243
1258
|
# store the kwargs
|
|
1244
|
-
for [a1, a2], t in zip(axes, tags):
|
|
1259
|
+
for [a1, a2], t in zip(axes, tags, strict=True):
|
|
1245
1260
|
if (
|
|
1246
1261
|
reset_existing_kwargs
|
|
1247
1262
|
and "edge_kwargs" in self.hive_plot_edges[a1][a2][t]
|
|
@@ -1544,7 +1559,7 @@ class HivePlot(BaseHivePlot):
|
|
|
1544
1559
|
sorting_variables: Union[Hashable, Dict[Hashable, Hashable]],
|
|
1545
1560
|
backend: SUPPORTED_VIZ_BACKENDS = "matplotlib", # type: ignore
|
|
1546
1561
|
repeat_axes: Union[bool, Hashable, List[Hashable]] = False,
|
|
1547
|
-
axes_order: Union[bool, List[Hashable]] = None,
|
|
1562
|
+
axes_order: Union[bool, List[Hashable]] | None = None,
|
|
1548
1563
|
rotation: float = 0,
|
|
1549
1564
|
angle_between_repeat_axes: float = 40,
|
|
1550
1565
|
axis_kwargs: Optional[Dict[Hashable, Dict]] = None,
|
|
@@ -1625,9 +1640,8 @@ class HivePlot(BaseHivePlot):
|
|
|
1625
1640
|
if axis_kwargs is not None:
|
|
1626
1641
|
for ax in axis_kwargs:
|
|
1627
1642
|
if ax not in valid_keys:
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
)
|
|
1643
|
+
msg = f"{ax} not in partition variables {valid_keys}."
|
|
1644
|
+
raise InvalidAxisNameError(msg)
|
|
1631
1645
|
self.update_axis(
|
|
1632
1646
|
axis_id=ax,
|
|
1633
1647
|
**axis_kwargs[ax],
|
|
@@ -1778,10 +1792,11 @@ class HivePlot(BaseHivePlot):
|
|
|
1778
1792
|
if check_repeat_in_name and any(
|
|
1779
1793
|
i[-7:] == "_repeat" for i in proposed_axes if isinstance(i, str)
|
|
1780
1794
|
):
|
|
1781
|
-
|
|
1795
|
+
msg = (
|
|
1782
1796
|
"Proposed axes names must never end with '_repeat', as this naming is reserved for repeat axes. "
|
|
1783
1797
|
f"Current names being generated parititioning with variable {self.partition_variable}: {proposed_axes}."
|
|
1784
1798
|
)
|
|
1799
|
+
raise RepeatInPartitionAxisNameError(msg)
|
|
1785
1800
|
|
|
1786
1801
|
def set_repeat_axes(
|
|
1787
1802
|
self,
|
|
@@ -1903,15 +1918,15 @@ class HivePlot(BaseHivePlot):
|
|
|
1903
1918
|
else: # pragma: no cover
|
|
1904
1919
|
# if no sorting variable is specified, raise an error
|
|
1905
1920
|
# but this should be impossible to get to in the code
|
|
1906
|
-
|
|
1921
|
+
msg = (
|
|
1907
1922
|
f"Repeat axis {repeat_axis_name} has no sorting variable specified.\n"
|
|
1908
1923
|
f"This should be impossible to hit! We'd appreciate if you could file a bug report here:\n"
|
|
1909
1924
|
"https://gitlab.com/geomdata/hiveplotlib/-/issues/new"
|
|
1910
1925
|
)
|
|
1926
|
+
raise MissingSortingVariableError(msg)
|
|
1911
1927
|
else: # pragma: no cover
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
)
|
|
1928
|
+
msg = "Unsupported format for `sorting_variables` parameter."
|
|
1929
|
+
raise NotImplementedError(msg)
|
|
1915
1930
|
self.update_sorting_variables(
|
|
1916
1931
|
sorting_variables=sorting_variables_dict,
|
|
1917
1932
|
build_hive_plot=False,
|
|
@@ -1982,7 +1997,7 @@ class HivePlot(BaseHivePlot):
|
|
|
1982
1997
|
"""
|
|
1983
1998
|
if not isinstance(sorting_variables, dict):
|
|
1984
1999
|
# if specifying same sorting variable for all axes, also propagate to the collapsed group axis name
|
|
1985
|
-
axes_to_update = list(self.axes.keys())
|
|
2000
|
+
axes_to_update = [*list(self.axes.keys()), self.collapsed_group_axis_name]
|
|
1986
2001
|
original_sorting_variable = sorting_variables
|
|
1987
2002
|
sorting_variables = {
|
|
1988
2003
|
k: original_sorting_variable for k, _ in self.partition
|
|
@@ -1997,10 +2012,11 @@ class HivePlot(BaseHivePlot):
|
|
|
1997
2012
|
# make sure all the sorting variables are valid before assigning new `sorting_variables` attribute
|
|
1998
2013
|
for k in sorting_variables:
|
|
1999
2014
|
if sorting_variables[k] not in self.nodes.data.columns:
|
|
2000
|
-
|
|
2015
|
+
msg = (
|
|
2001
2016
|
f"Invalid `sorting_variables` ('{sorting_variables[k]}') provided for axis {k}, "
|
|
2002
2017
|
f"must be column of node data: {self.nodes.data.columns.to_list()}"
|
|
2003
2018
|
)
|
|
2019
|
+
raise InvalidSortingVariableError(msg)
|
|
2004
2020
|
|
|
2005
2021
|
# otherwise, double check we have valid axis values
|
|
2006
2022
|
proposed_axes = list(sorting_variables.keys())
|
|
@@ -2017,11 +2033,12 @@ class HivePlot(BaseHivePlot):
|
|
|
2017
2033
|
set(self.sorting_variables.keys())
|
|
2018
2034
|
)
|
|
2019
2035
|
if len(missing_axes) > 0:
|
|
2020
|
-
|
|
2036
|
+
msg = (
|
|
2021
2037
|
f"Provided `sorting_variables` axes {list(proposed_axes)} do not cover *all* the necessary axes "
|
|
2022
2038
|
f"specified by the current partition: ({list(expected_axes_names)}).\n"
|
|
2023
2039
|
f"The following axes specifications must be included: {list(missing_axes)}"
|
|
2024
2040
|
)
|
|
2041
|
+
raise MissingSortingVariableError(msg)
|
|
2025
2042
|
|
|
2026
2043
|
update_axis_kwargs = {}
|
|
2027
2044
|
if reset_vmin_and_vmax:
|
|
@@ -2057,10 +2074,11 @@ class HivePlot(BaseHivePlot):
|
|
|
2057
2074
|
:return: ``None``.
|
|
2058
2075
|
"""
|
|
2059
2076
|
if partition_variable not in self.nodes.data.columns:
|
|
2060
|
-
|
|
2077
|
+
msg = (
|
|
2061
2078
|
f"Invalid `partition_variable` ('{partition_variable}') provided, "
|
|
2062
2079
|
f"must be column of node data: {self.nodes.data.columns.to_list()}"
|
|
2063
2080
|
)
|
|
2081
|
+
raise InvalidPartitionVariableError(msg)
|
|
2064
2082
|
|
|
2065
2083
|
partition = self.nodes.data.groupby(partition_variable)
|
|
2066
2084
|
|
|
@@ -2260,21 +2278,23 @@ class HivePlot(BaseHivePlot):
|
|
|
2260
2278
|
)
|
|
2261
2279
|
|
|
2262
2280
|
if unacceptable_names:
|
|
2263
|
-
|
|
2281
|
+
msg = (
|
|
2264
2282
|
"Axes order set with incorrect names "
|
|
2265
2283
|
f"for the current partition variable {self.partition_variable}.\n"
|
|
2266
2284
|
f"Axes names that must be provided (in any order): {list(valid_names)}.\n"
|
|
2267
2285
|
"(Can also include `None` to collapse any unspecifed groups from the partition into a single axis.)\n"
|
|
2268
2286
|
f"Names provided: {list(axes)}."
|
|
2269
2287
|
)
|
|
2288
|
+
raise InvalidAxesOrderError(msg)
|
|
2270
2289
|
|
|
2271
2290
|
if None in axes:
|
|
2272
2291
|
unspecified_axes = set(valid_names).difference(set(axes))
|
|
2273
2292
|
if len(unspecified_axes) == 0:
|
|
2274
|
-
|
|
2293
|
+
msg = (
|
|
2275
2294
|
"Provided `None` in for axes order, but no unspecified axes to collapse onto this 'Other' axis.\n"
|
|
2276
2295
|
f"Axes order names provided: {list(axes)}."
|
|
2277
2296
|
)
|
|
2297
|
+
raise InvalidAxesOrderError(msg)
|
|
2278
2298
|
|
|
2279
2299
|
if collapsed_group_axis_name is not None:
|
|
2280
2300
|
self.collapsed_group_axis_name = collapsed_group_axis_name
|
|
@@ -2309,10 +2329,11 @@ class HivePlot(BaseHivePlot):
|
|
|
2309
2329
|
check_collapsed_group_sorting_variable
|
|
2310
2330
|
and self.collapsed_group_axis_name not in self.sorting_variables
|
|
2311
2331
|
):
|
|
2312
|
-
|
|
2332
|
+
msg = (
|
|
2313
2333
|
f"Sorting variable for collapsed group axis {self.collapsed_group_axis_name} not provided and "
|
|
2314
2334
|
f"not available in the current sorting variables: {self.sorting_variables}"
|
|
2315
2335
|
)
|
|
2336
|
+
raise MissingSortingVariableError(msg)
|
|
2316
2337
|
|
|
2317
2338
|
# use new name for axes downstream
|
|
2318
2339
|
axes = [
|
|
@@ -2324,12 +2345,13 @@ class HivePlot(BaseHivePlot):
|
|
|
2324
2345
|
# if we are requiring all partition names, then make sure we have all of them
|
|
2325
2346
|
missing_partition_names = set(valid_names).difference(set(axes))
|
|
2326
2347
|
if len(missing_partition_names) > 0:
|
|
2327
|
-
|
|
2348
|
+
msg = (
|
|
2328
2349
|
f"Provided axes order {list(axes)} does not include all partition names: {list(valid_names)}.\n"
|
|
2329
2350
|
f"Missing partition names: {list(missing_partition_names)}.\n"
|
|
2330
2351
|
"If you want to only show a subset of the partition names, then run set_partition() with the "
|
|
2331
2352
|
"desired `axes_order`."
|
|
2332
2353
|
)
|
|
2354
|
+
raise InvalidAxesOrderError(msg)
|
|
2333
2355
|
|
|
2334
2356
|
# preserve original hive plot edges info so we can bring back the user-provided kwargs if desired
|
|
2335
2357
|
original_edge_info = deepcopy(self.hive_plot_edges)
|
|
@@ -2520,9 +2542,8 @@ class HivePlot(BaseHivePlot):
|
|
|
2520
2542
|
:return: ``None``.
|
|
2521
2543
|
"""
|
|
2522
2544
|
if backend not in get_args(SUPPORTED_VIZ_BACKENDS):
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
)
|
|
2545
|
+
msg = f"Requested backend '{backend}' not among supported backends {get_args(SUPPORTED_VIZ_BACKENDS)}."
|
|
2546
|
+
raise InvalidVizBackendError(msg)
|
|
2526
2547
|
self.backend = backend
|
|
2527
2548
|
|
|
2528
2549
|
return
|
|
@@ -2622,10 +2643,11 @@ class HivePlot(BaseHivePlot):
|
|
|
2622
2643
|
partition_id_1 not in valid_partition_variables
|
|
2623
2644
|
or partition_id_2 not in valid_partition_variables
|
|
2624
2645
|
):
|
|
2625
|
-
|
|
2646
|
+
msg = (
|
|
2626
2647
|
"Invalid partition variables (`partition_id_1` or `partition_id_2`) provided. "
|
|
2627
2648
|
f"Must be one of: {valid_partition_variables}."
|
|
2628
2649
|
)
|
|
2650
|
+
raise InvalidPartitionVariableError(msg)
|
|
2629
2651
|
|
|
2630
2652
|
# default params will come from original settings
|
|
2631
2653
|
edges_instantiation_params = {
|
|
@@ -2656,11 +2678,10 @@ class HivePlot(BaseHivePlot):
|
|
|
2656
2678
|
and len(self.hive_plot_edges[p1][p2]) > 0
|
|
2657
2679
|
):
|
|
2658
2680
|
if len(self.hive_plot_edges[p1][p2]) > 1 and tag is None:
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
)
|
|
2681
|
+
msg = "`tag` must be specified when there are multiple tags."
|
|
2682
|
+
raise UnspecifiedTagError(msg)
|
|
2662
2683
|
if tag is None:
|
|
2663
|
-
tag =
|
|
2684
|
+
tag = next(iter(self.hive_plot_edges[p1][p2].keys()))
|
|
2664
2685
|
if (
|
|
2665
2686
|
tag in self.hive_plot_edges[p1][p2]
|
|
2666
2687
|
and "curves" in self.hive_plot_edges[p1][p2][tag]
|
|
@@ -2827,10 +2848,11 @@ class HivePlot(BaseHivePlot):
|
|
|
2827
2848
|
|
|
2828
2849
|
if sorting_variable is not None:
|
|
2829
2850
|
if sorting_variable not in self.nodes.data.columns:
|
|
2830
|
-
|
|
2851
|
+
msg = (
|
|
2831
2852
|
f"Invalid `sorting_variable` ('{sorting_variable}') provided for axis {axis_id}, "
|
|
2832
2853
|
f"must be column of node data: {self.nodes.data.columns.to_list()}"
|
|
2833
2854
|
)
|
|
2855
|
+
raise InvalidSortingVariableError(msg)
|
|
2834
2856
|
# old edges with axis invalid if user changed sorting variable
|
|
2835
2857
|
self.reset_edges(axis_id_1=axis_id)
|
|
2836
2858
|
node_placement_params["sorting_feature_to_use"] = sorting_variable
|
|
@@ -3494,11 +3516,12 @@ class HivePlot(BaseHivePlot):
|
|
|
3494
3516
|
if order_values != expected_values or len(order) != len(
|
|
3495
3517
|
self._edge_kwarg_hierarchy
|
|
3496
3518
|
):
|
|
3497
|
-
|
|
3519
|
+
msg = (
|
|
3498
3520
|
"Invalid provided `order` to `HivePlot.edge_kwarg_hierarchy`.\n"
|
|
3499
3521
|
"All of the following values must be provided exactly once:\n"
|
|
3500
3522
|
f"{list(self.edge_plotting_keyword_arguments.keys())}"
|
|
3501
3523
|
)
|
|
3524
|
+
raise InvalidEdgeKwargHierarchyError(msg)
|
|
3502
3525
|
|
|
3503
3526
|
self._edge_kwarg_hierarchy = list(order)
|
|
3504
3527
|
|
|
@@ -3708,7 +3731,7 @@ def hive_plot_n_axes(
|
|
|
3708
3731
|
axes_assignments: List[List[Union[Hashable, None]]],
|
|
3709
3732
|
sorting_variables: List[Hashable],
|
|
3710
3733
|
nodes: Union[NodeCollection, List[Node]] = None,
|
|
3711
|
-
node_list: list[Node] = None,
|
|
3734
|
+
node_list: list[Node] | None = None,
|
|
3712
3735
|
axes_names: Optional[List[Hashable]] = None,
|
|
3713
3736
|
repeat_axes: Optional[List[bool]] = None,
|
|
3714
3737
|
vmins: Optional[List[float]] = None,
|
|
@@ -156,10 +156,11 @@ class NodeCollection:
|
|
|
156
156
|
len(np.unique(self.data[self.unique_id_column].values))
|
|
157
157
|
!= self.data.shape[0]
|
|
158
158
|
):
|
|
159
|
-
|
|
159
|
+
msg = (
|
|
160
160
|
"Found repeat unique IDs:\n"
|
|
161
161
|
f"{self.data[self.data.duplicated(subset=self.unique_id_column, keep=False)]}"
|
|
162
162
|
)
|
|
163
|
+
raise RepeatUniqueNodeIDsError(msg)
|
|
163
164
|
self.node_viz_kwargs = {} if node_viz_kwargs is None else node_viz_kwargs.copy()
|
|
164
165
|
|
|
165
166
|
def copy(self) -> "NodeCollection":
|
|
@@ -217,10 +218,11 @@ class NodeCollection:
|
|
|
217
218
|
protected name for internal use.
|
|
218
219
|
"""
|
|
219
220
|
if data_column not in self.data.columns:
|
|
220
|
-
|
|
221
|
+
msg = (
|
|
221
222
|
f"Invalid `partition_variable` ({data_column}) provided, "
|
|
222
223
|
f"must be column of node data: {self.data.columns.to_list()}"
|
|
223
224
|
)
|
|
225
|
+
raise InvalidPartitionVariableError(msg)
|
|
224
226
|
if partition_variable_name is None:
|
|
225
227
|
i = 0
|
|
226
228
|
# keep trying new names til we get a unique one
|
|
@@ -231,9 +233,8 @@ class NodeCollection:
|
|
|
231
233
|
i += 1
|
|
232
234
|
else:
|
|
233
235
|
if partition_variable_name.endswith("_collapsed_axis"):
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
236
|
+
msg = "Cannot use partition variable name ending in `_collapsed_axis`."
|
|
237
|
+
raise InvalidPartitionVariableError(msg)
|
|
237
238
|
|
|
238
239
|
# int cutoffs dictates quantile cut, otherwise cut
|
|
239
240
|
if not isinstance(cutoffs, int):
|
|
@@ -203,6 +203,7 @@ class P2CP:
|
|
|
203
203
|
axis_kwargs,
|
|
204
204
|
vmins,
|
|
205
205
|
vmaxes,
|
|
206
|
+
strict=True,
|
|
206
207
|
):
|
|
207
208
|
if c in self.axes:
|
|
208
209
|
c += "\nRepeat"
|
|
@@ -394,8 +395,8 @@ class P2CP:
|
|
|
394
395
|
# want to loop over the nested tags, not the axes like with hive plots
|
|
395
396
|
# (since every point in a tag is a complete loop)
|
|
396
397
|
# so let's just grab the first axis pair we can find and grab those tags, then loop over the tags instead
|
|
397
|
-
temp_first_axis =
|
|
398
|
-
temp_second_axis =
|
|
398
|
+
temp_first_axis = next(iter(edge_info.keys()))
|
|
399
|
+
temp_second_axis = next(iter(edge_info[temp_first_axis].keys()))
|
|
399
400
|
|
|
400
401
|
for tag in edge_info[temp_first_axis][temp_second_axis]:
|
|
401
402
|
new_dict[tag] = {}
|
|
@@ -146,9 +146,8 @@ def edge_viz_preparation(
|
|
|
146
146
|
stacklevel=3,
|
|
147
147
|
)
|
|
148
148
|
else: # pragma: no cover
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
149
|
+
msg = "No instances should ever reach this point..."
|
|
150
|
+
raise NotImplementedError(msg)
|
|
152
151
|
# only warn once per tag over all axes
|
|
153
152
|
elif name == "P2CP" and tag not in already_warned_p2cp_tags:
|
|
154
153
|
warnings.warn(
|
|
@@ -218,10 +217,11 @@ def hover_input_check(
|
|
|
218
217
|
if pd.api.types.is_list_like(hover):
|
|
219
218
|
for h in hover:
|
|
220
219
|
if h not in ["nodes", "edges", "axes"]:
|
|
221
|
-
|
|
220
|
+
msg = (
|
|
222
221
|
"Hover information is only supported for `'nodes'`, `'axes'`, and / or `'edges'` "
|
|
223
222
|
f"(provided values: {hover})"
|
|
224
223
|
)
|
|
224
|
+
raise InvalidHoverVariableError(msg)
|
|
225
225
|
return
|
|
226
226
|
|
|
227
227
|
|
|
@@ -8,9 +8,8 @@ try:
|
|
|
8
8
|
from bokeh.models import ColumnDataSource, Label, Range1d
|
|
9
9
|
from bokeh.plotting import figure
|
|
10
10
|
except ImportError as ie: # pragma: no cover
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
) from ie
|
|
11
|
+
msg = "bokeh not installed, but can be installed by running `pip install hiveplotlib[bokeh]`"
|
|
12
|
+
raise ImportError(msg) from ie
|
|
14
13
|
|
|
15
14
|
import warnings
|
|
16
15
|
from typing import Hashable, List, Literal, Optional, Union
|
|
@@ -606,7 +605,7 @@ def edge_viz(
|
|
|
606
605
|
hive_plot.edges.to_column_name,
|
|
607
606
|
]
|
|
608
607
|
else ""
|
|
609
|
-
for i in hive_plot.edges._data[
|
|
608
|
+
for i in hive_plot.edges._data[next(iter(tags_to_plot))].columns
|
|
610
609
|
]
|
|
611
610
|
right_arrow = "➡"
|
|
612
611
|
tooltips = f"""
|
|
@@ -21,10 +21,11 @@ try:
|
|
|
21
21
|
import datashader as ds
|
|
22
22
|
import seaborn as sns
|
|
23
23
|
except ImportError as ie: # pragma: no cover
|
|
24
|
-
|
|
24
|
+
msg = (
|
|
25
25
|
"Datashader or seaborn not installed, but can be installed by running "
|
|
26
26
|
"`pip install hiveplotlib[datashader]`"
|
|
27
|
-
)
|
|
27
|
+
)
|
|
28
|
+
raise ImportError(msg) from ie
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def datashade_edges_mpl(
|
|
@@ -4,16 +4,13 @@
|
|
|
4
4
|
Currently, ``hiveplotlib`` supports a ``bokeh`` and ``matplotlib`` backend for ``holoviews``.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
# __all__ = []
|
|
8
|
-
|
|
9
7
|
try:
|
|
10
8
|
import holoviews as hv
|
|
11
9
|
from bokeh.models import HoverTool
|
|
12
10
|
from holoviews import dim
|
|
13
11
|
except ImportError as ie: # pragma: no cover
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
) from ie
|
|
12
|
+
msg = "`holoviews` not installed, but can be installed by running `pip install hiveplotlib[holoviews]`"
|
|
13
|
+
raise ImportError(msg) from ie
|
|
17
14
|
|
|
18
15
|
import warnings
|
|
19
16
|
from typing import Hashable, List, Literal, Optional, Union, get_args
|
|
@@ -262,7 +259,7 @@ def axes_viz(
|
|
|
262
259
|
kdims=[original_to_sanitized_map[i] for i in ["x_0", "y_0", "x_1", "y_1"]],
|
|
263
260
|
vdims=[
|
|
264
261
|
original_to_sanitized_map[i]
|
|
265
|
-
for i in ["long_name"
|
|
262
|
+
for i in ["long_name", *list(axis_metadata_variables)]
|
|
266
263
|
if i not in ["x_0", "x_1", "y_0", "y_1"]
|
|
267
264
|
],
|
|
268
265
|
).opts(
|
|
@@ -647,10 +644,13 @@ def edge_viz(
|
|
|
647
644
|
| hive_plot.hive_plot_edges[a0][a1][tag]["edge_kwargs"]
|
|
648
645
|
)
|
|
649
646
|
if backend == "bokeh" and "line_color" in final_edge_kwargs:
|
|
650
|
-
|
|
647
|
+
msg = (
|
|
651
648
|
"Hiveplotlib does not support using the 'line_color' parameter"
|
|
652
649
|
" with the `holoviews-bokeh` backend. "
|
|
653
|
-
"Please switch to using the 'color' parameter instead."
|
|
650
|
+
"Please switch to using the 'color' parameter instead."
|
|
651
|
+
)
|
|
652
|
+
raise ValueError(
|
|
653
|
+
msg,
|
|
654
654
|
)
|
|
655
655
|
# if any kwarg value corresponds to an edge data column name, use the edge data values
|
|
656
656
|
keys_vals = final_edge_kwargs.copy().items()
|
|
@@ -693,7 +693,9 @@ def edge_viz(
|
|
|
693
693
|
]
|
|
694
694
|
contours = [
|
|
695
695
|
{"x": x, "y": y, **data_dict}
|
|
696
|
-
for (x, y, data_dict) in zip(
|
|
696
|
+
for (x, y, data_dict) in zip(
|
|
697
|
+
xs, ys, data_dicts, strict=True
|
|
698
|
+
)
|
|
697
699
|
]
|
|
698
700
|
|
|
699
701
|
# HACK: solution to https://github.com/holoviz/holoviews/issues/6469 for the moment
|
|
@@ -740,7 +742,7 @@ def edge_viz(
|
|
|
740
742
|
hive_plot.edges.to_column_name,
|
|
741
743
|
]
|
|
742
744
|
else ""
|
|
743
|
-
for i in hive_plot.edges._data[
|
|
745
|
+
for i in hive_plot.edges._data[next(iter(tags_to_plot))].columns
|
|
744
746
|
]
|
|
745
747
|
right_arrow = "➡"
|
|
746
748
|
tooltips = f"""
|
|
@@ -41,9 +41,8 @@ def input_check(
|
|
|
41
41
|
hive_plot = instance._hiveplot
|
|
42
42
|
name = "P2CP"
|
|
43
43
|
else:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
44
|
+
msg = "Can only handle `HivePlot`, `BaseHivePlot`, and `P2CP` instances"
|
|
45
|
+
raise NotImplementedError(msg)
|
|
47
46
|
|
|
48
47
|
warning_raised = False
|
|
49
48
|
|
|
@@ -124,8 +123,7 @@ def input_check(
|
|
|
124
123
|
)
|
|
125
124
|
warning_raised = True
|
|
126
125
|
else: # pragma: no cover
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
126
|
+
msg = f"`objects_to plot` must be one of 'axes', 'edges', or 'nodes', but user provided '{objects_to_plot}'."
|
|
127
|
+
raise NotImplementedError(msg)
|
|
130
128
|
|
|
131
129
|
return hive_plot, name, warning_raised
|
|
@@ -58,7 +58,7 @@ def _matplotlib_fig_setup(
|
|
|
58
58
|
fig, ax = plt.subplots(**fig_kwargs)
|
|
59
59
|
|
|
60
60
|
if center_plot and hive_plot.max_polar_end is not None:
|
|
61
|
-
ax.
|
|
61
|
+
ax.set_aspect("equal", adjustable="box")
|
|
62
62
|
# center plot at (0, 0)
|
|
63
63
|
max_radius = hive_plot.max_polar_end
|
|
64
64
|
# throw in a minor buffer
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
try:
|
|
8
8
|
import plotly.graph_objects as go
|
|
9
9
|
except ImportError as ie: # pragma: no cover
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
) from ie
|
|
10
|
+
msg = "plotly not installed, but can be installed by running `pip install hiveplotlib[plotly]`"
|
|
11
|
+
raise ImportError(msg) from ie
|
|
13
12
|
|
|
14
13
|
import warnings
|
|
15
14
|
from typing import Hashable, List, Literal, Optional, Union
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hiveplotlib
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.2
|
|
4
4
|
Summary: Visualize Network Data with Hive Plots
|
|
5
5
|
Author-email: Gary Koplik <gary.koplik@geomdata.com>
|
|
6
6
|
License: Copyright (c) 2020 - 2024, Geometric Data Analytics, Inc.
|
|
@@ -34,7 +34,7 @@ License: Copyright (c) 2020 - 2024, Geometric Data Analytics, Inc.
|
|
|
34
34
|
|
|
35
35
|
Project-URL: Documentation, https://hiveplotlib.readthedocs.io/stable/
|
|
36
36
|
Project-URL: Source, https://gitlab.com/geomdata/hiveplotlib
|
|
37
|
-
Requires-Python: >=3.
|
|
37
|
+
Requires-Python: >=3.10
|
|
38
38
|
Description-Content-Type: text/markdown
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: matplotlib
|
|
@@ -48,13 +48,13 @@ Requires-Dist: datashader; extra == "datashader"
|
|
|
48
48
|
Requires-Dist: numba>0.54.0; extra == "datashader"
|
|
49
49
|
Requires-Dist: seaborn; extra == "datashader"
|
|
50
50
|
Provides-Extra: dev
|
|
51
|
-
Requires-Dist: bokeh
|
|
51
|
+
Requires-Dist: bokeh; extra == "dev"
|
|
52
52
|
Requires-Dist: cartopy; extra == "dev"
|
|
53
53
|
Requires-Dist: dask[dataframe]; extra == "dev"
|
|
54
54
|
Requires-Dist: datashader; extra == "dev"
|
|
55
55
|
Requires-Dist: flexitext; extra == "dev"
|
|
56
56
|
Requires-Dist: geopandas; extra == "dev"
|
|
57
|
-
Requires-Dist: holoviews
|
|
57
|
+
Requires-Dist: holoviews; extra == "dev"
|
|
58
58
|
Requires-Dist: jupyter; extra == "dev"
|
|
59
59
|
Requires-Dist: networkx; extra == "dev"
|
|
60
60
|
Requires-Dist: numba>0.54.0; extra == "dev"
|
|
@@ -70,8 +70,8 @@ Requires-Dist: sphinx; extra == "docs"
|
|
|
70
70
|
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
71
71
|
Requires-Dist: toml; extra == "docs"
|
|
72
72
|
Provides-Extra: holoviews
|
|
73
|
-
Requires-Dist: bokeh
|
|
74
|
-
Requires-Dist: holoviews
|
|
73
|
+
Requires-Dist: bokeh; extra == "holoviews"
|
|
74
|
+
Requires-Dist: holoviews; extra == "holoviews"
|
|
75
75
|
Requires-Dist: numba>0.54.0; extra == "holoviews"
|
|
76
76
|
Provides-Extra: networkx
|
|
77
77
|
Requires-Dist: networkx; extra == "networkx"
|
|
@@ -12,13 +12,13 @@ numba>0.54.0
|
|
|
12
12
|
seaborn
|
|
13
13
|
|
|
14
14
|
[dev]
|
|
15
|
-
bokeh
|
|
15
|
+
bokeh
|
|
16
16
|
cartopy
|
|
17
17
|
dask[dataframe]
|
|
18
18
|
datashader
|
|
19
19
|
flexitext
|
|
20
20
|
geopandas
|
|
21
|
-
holoviews
|
|
21
|
+
holoviews
|
|
22
22
|
jupyter
|
|
23
23
|
networkx
|
|
24
24
|
numba>0.54.0
|
|
@@ -36,8 +36,8 @@ sphinx-copybutton
|
|
|
36
36
|
toml
|
|
37
37
|
|
|
38
38
|
[holoviews]
|
|
39
|
-
bokeh
|
|
40
|
-
holoviews
|
|
39
|
+
bokeh
|
|
40
|
+
holoviews
|
|
41
41
|
numba>0.54.0
|
|
42
42
|
|
|
43
43
|
[networkx]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|