howso-visuals 2.0.10__py3-none-any.whl → 2.1.1__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.
- howso/visuals/__init__.py +2 -0
- howso/visuals/graph.py +221 -0
- howso/visuals/tests/conftest.py +6 -12
- howso/visuals/tests/test_graph.py +35 -0
- howso/visuals/tests/test_plot.py +24 -25
- {howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/METADATA +3 -2
- howso_visuals-2.1.1.dist-info/RECORD +22 -0
- {howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/licenses/LICENSE-3RD-PARTY.txt +65 -19
- howso_visuals-2.0.10.dist-info/RECORD +0 -20
- {howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/WHEEL +0 -0
- {howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/licenses/LICENSE.txt +0 -0
- {howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/top_level.txt +0 -0
howso/visuals/__init__.py
CHANGED
howso/visuals/graph.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
from collections.abc import Callable, Mapping
|
|
2
|
+
from typing import Any, SupportsInt, TypeAlias
|
|
3
|
+
|
|
4
|
+
import networkx as nx
|
|
5
|
+
import numpy as np
|
|
6
|
+
import plotly.graph_objects as go
|
|
7
|
+
from sklearn.preprocessing import minmax_scale
|
|
8
|
+
|
|
9
|
+
LayoutMapping: TypeAlias = Mapping[Any, tuple[float, float]]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _create_edge_annotations(
|
|
13
|
+
G: nx.Graph, # noqa: N803
|
|
14
|
+
pos: LayoutMapping,
|
|
15
|
+
edge_attr: str | None = None,
|
|
16
|
+
edge_attr_sigfigs: SupportsInt | None = 4,
|
|
17
|
+
label_edges: bool = True,
|
|
18
|
+
) -> tuple[list[go.layout.Annotation], list[dict[str, Any]]]:
|
|
19
|
+
# Annotations are created to show the edges between nodes,
|
|
20
|
+
# while invisible shapes with labels are created to label them with the edge weight.
|
|
21
|
+
annotations = []
|
|
22
|
+
shapes = []
|
|
23
|
+
directed = nx.is_directed(G)
|
|
24
|
+
|
|
25
|
+
widths = None
|
|
26
|
+
unscaled_widths = None
|
|
27
|
+
if edge_attr is not None:
|
|
28
|
+
unscaled_widths = [d[edge_attr] for _, _, d in G.edges(data=True)]
|
|
29
|
+
widths = minmax_scale(np.array(unscaled_widths).reshape(-1, 1), (2, 5))
|
|
30
|
+
widths = widths.reshape(-1)
|
|
31
|
+
|
|
32
|
+
edge_blacklist = set()
|
|
33
|
+
|
|
34
|
+
for i, (s, d) in enumerate(G.edges()):
|
|
35
|
+
if (s, d) in edge_blacklist:
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
x0, y0 = pos[s]
|
|
39
|
+
x1, y1 = pos[d]
|
|
40
|
+
width = widths[i] if widths is not None else 2
|
|
41
|
+
|
|
42
|
+
if directed and G.has_edge(d, s):
|
|
43
|
+
edge_blacklist.add((d, s))
|
|
44
|
+
arrowside = "end+start"
|
|
45
|
+
elif not directed:
|
|
46
|
+
arrowside = "none"
|
|
47
|
+
else:
|
|
48
|
+
arrowside = "end"
|
|
49
|
+
|
|
50
|
+
annotations.append(
|
|
51
|
+
go.layout.Annotation(
|
|
52
|
+
ax=x0,
|
|
53
|
+
ay=y0,
|
|
54
|
+
axref="x",
|
|
55
|
+
ayref="y",
|
|
56
|
+
x=x1,
|
|
57
|
+
y=y1,
|
|
58
|
+
xref="x",
|
|
59
|
+
yref="y",
|
|
60
|
+
showarrow=True,
|
|
61
|
+
arrowhead=4,
|
|
62
|
+
standoff=40.5,
|
|
63
|
+
startstandoff=37.5,
|
|
64
|
+
arrowside=arrowside,
|
|
65
|
+
arrowwidth=width,
|
|
66
|
+
opacity=0.8,
|
|
67
|
+
captureevents=True,
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if label_edges:
|
|
72
|
+
if edge_attr_sigfigs is not None and unscaled_widths is not None:
|
|
73
|
+
shape_label = f"{round(unscaled_widths[i], edge_attr_sigfigs)}"
|
|
74
|
+
elif unscaled_widths is not None:
|
|
75
|
+
shape_label = f"{unscaled_widths[i]}"
|
|
76
|
+
else:
|
|
77
|
+
shape_label = ""
|
|
78
|
+
else:
|
|
79
|
+
shape_label = ""
|
|
80
|
+
|
|
81
|
+
shape_label = (
|
|
82
|
+
'<span style="text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff;">'
|
|
83
|
+
f"{shape_label}</span>"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
shapes.append(
|
|
87
|
+
dict(
|
|
88
|
+
type="line",
|
|
89
|
+
x0=x0,
|
|
90
|
+
y0=y0,
|
|
91
|
+
x1=x1,
|
|
92
|
+
y1=y1,
|
|
93
|
+
xref="x",
|
|
94
|
+
yref="y",
|
|
95
|
+
label=dict(text=shape_label),
|
|
96
|
+
opacity=0,
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return annotations, shapes
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def plot_graph(
|
|
104
|
+
G: nx.Graph, # noqa: N803
|
|
105
|
+
*,
|
|
106
|
+
edge_attr_sigfigs: SupportsInt | None = 4,
|
|
107
|
+
edge_attr: str | None = None,
|
|
108
|
+
label_edges: bool = True,
|
|
109
|
+
layout: Callable[[nx.Graph], LayoutMapping] = nx.shell_layout,
|
|
110
|
+
node_color: list[float] | None = None,
|
|
111
|
+
subtitle: str | None = None,
|
|
112
|
+
title: str = "Causal Graph",
|
|
113
|
+
) -> go.Figure:
|
|
114
|
+
"""
|
|
115
|
+
Plot a ``networkx`` graph using `Plotly`.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
G : nx.Graph
|
|
120
|
+
The graph to plot.
|
|
121
|
+
edge_attr : str, optional
|
|
122
|
+
The name of the edge attribute to use when scaling the size of the edges. This should
|
|
123
|
+
be an attribute that is contained within ``G``.
|
|
124
|
+
edge_attr_sigfigs : SupportsInt | None, default 4
|
|
125
|
+
The number of significant figures to round to when labelling each edge. If None, no rounding
|
|
126
|
+
will be performed.
|
|
127
|
+
label_edges : bool, default True
|
|
128
|
+
Whether to label plotted edges.
|
|
129
|
+
layout : Callable[nx.Graph, Mapping[Any, tuple[float, float]]], default nx.shell_layout
|
|
130
|
+
A callable which generates a mapping of nodes to ``(x, y)`` coordinates.
|
|
131
|
+
node_color : list[float], optional
|
|
132
|
+
The data to use when determining the color for each node.
|
|
133
|
+
title : str, default "Causal Graph"
|
|
134
|
+
The title of the plot.
|
|
135
|
+
subtitle : str, optional
|
|
136
|
+
The subtitle of the plot.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
go.Figure
|
|
141
|
+
The resultant `Plotly` figure.
|
|
142
|
+
"""
|
|
143
|
+
pos = layout(G, center=(1, 1))
|
|
144
|
+
|
|
145
|
+
text = []
|
|
146
|
+
node_x = []
|
|
147
|
+
node_y = []
|
|
148
|
+
for node in G.nodes():
|
|
149
|
+
text.append(node)
|
|
150
|
+
x, y = pos[node]
|
|
151
|
+
node_x.append(x)
|
|
152
|
+
node_y.append(y)
|
|
153
|
+
|
|
154
|
+
# This places a 1px black border around the node labels.
|
|
155
|
+
text = [
|
|
156
|
+
f'<span style="text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;">{t}</span>'
|
|
157
|
+
for t in text
|
|
158
|
+
]
|
|
159
|
+
hovertemplate = "<b>%{text}</b>"
|
|
160
|
+
if node_color is not None:
|
|
161
|
+
hovertemplate += "<br>Destination MIR: %{customdata[0]:.4f}</br>"
|
|
162
|
+
|
|
163
|
+
node_trace = go.Scatter(
|
|
164
|
+
x=node_x,
|
|
165
|
+
y=node_y,
|
|
166
|
+
text=text,
|
|
167
|
+
textposition="middle center",
|
|
168
|
+
mode="markers+text",
|
|
169
|
+
marker=dict(
|
|
170
|
+
color=node_color,
|
|
171
|
+
coloraxis="coloraxis",
|
|
172
|
+
size=75,
|
|
173
|
+
),
|
|
174
|
+
zorder=999,
|
|
175
|
+
textfont=dict(color="white"),
|
|
176
|
+
name="Nodes",
|
|
177
|
+
customdata=[[x] for x in node_color] if node_color is not None else None,
|
|
178
|
+
hovertemplate=hovertemplate,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
annotations, shapes = _create_edge_annotations(
|
|
182
|
+
G,
|
|
183
|
+
pos,
|
|
184
|
+
edge_attr=edge_attr,
|
|
185
|
+
edge_attr_sigfigs=edge_attr_sigfigs,
|
|
186
|
+
label_edges=label_edges,
|
|
187
|
+
)
|
|
188
|
+
fig = go.Figure(
|
|
189
|
+
layout=go.Layout(
|
|
190
|
+
title=dict(text="<br>Network graph made with Python", font=dict(size=16)),
|
|
191
|
+
showlegend=False,
|
|
192
|
+
hovermode="closest",
|
|
193
|
+
margin=dict(b=20, l=5, r=5, t=40),
|
|
194
|
+
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False, constrain="domain"),
|
|
195
|
+
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False, constrain="domain"),
|
|
196
|
+
annotations=annotations,
|
|
197
|
+
)
|
|
198
|
+
)
|
|
199
|
+
fig.update_layout(
|
|
200
|
+
coloraxis=dict(
|
|
201
|
+
colorscale="Bluered_r",
|
|
202
|
+
cmin=1,
|
|
203
|
+
cmax=30,
|
|
204
|
+
cmid=15,
|
|
205
|
+
colorbar=dict(
|
|
206
|
+
title="Missing Information Ratio", tickvals=[1, 3, 15, 30], ticktext=["1", "3", "15", "≥30"]
|
|
207
|
+
),
|
|
208
|
+
reversescale=True,
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
for s in shapes:
|
|
213
|
+
fig.add_shape(**s)
|
|
214
|
+
fig.add_trace(node_trace)
|
|
215
|
+
|
|
216
|
+
fig.update_layout(
|
|
217
|
+
title=dict(text=title, subtitle=dict(text=subtitle)),
|
|
218
|
+
width=1000,
|
|
219
|
+
height=750,
|
|
220
|
+
)
|
|
221
|
+
return fig
|
howso/visuals/tests/conftest.py
CHANGED
|
@@ -17,33 +17,27 @@ def iris() -> pd.DataFrame:
|
|
|
17
17
|
iris_path = iris_path.resolve()
|
|
18
18
|
|
|
19
19
|
df = pd.read_csv(iris_path / "iris.csv")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
yield df
|
|
20
|
+
return df.sample(frac=1).reset_index(drop=True)
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
@pytest.fixture(scope="session")
|
|
26
24
|
def iris_train(iris) -> pd.DataFrame:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
yield iris_train
|
|
25
|
+
return iris.truncate(after=75)
|
|
30
26
|
|
|
31
27
|
|
|
32
28
|
@pytest.fixture(scope="session")
|
|
33
29
|
def iris_test(iris, iris_train) -> pd.DataFrame:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
yield iris_test
|
|
30
|
+
return iris[~iris.index.isin(iris_train.index)]
|
|
37
31
|
|
|
38
32
|
|
|
39
33
|
@pytest.fixture(scope="session")
|
|
40
34
|
def iris_features(iris_train) -> FeatureAttributesBase:
|
|
41
35
|
features = infer_feature_attributes(iris_train)
|
|
42
|
-
for
|
|
36
|
+
for f_value in features.values():
|
|
43
37
|
if f_value["type"] in ["nominal", "ordinal"]:
|
|
44
38
|
f_value["non_sensitive"] = True
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
return features
|
|
47
41
|
|
|
48
42
|
|
|
49
43
|
@pytest.fixture(scope="session")
|
|
@@ -52,4 +46,4 @@ def iris_trainee(iris_train, iris_features) -> Trainee:
|
|
|
52
46
|
t.train(iris_train)
|
|
53
47
|
t.analyze()
|
|
54
48
|
|
|
55
|
-
|
|
49
|
+
return t
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import networkx as nx
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from howso.visuals.graph import _create_edge_annotations, plot_graph
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.fixture
|
|
8
|
+
def G(): # noqa: N802
|
|
9
|
+
return nx.random_geometric_graph(10, 0.5)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def pos(G): # noqa: N803
|
|
14
|
+
return nx.shell_layout(G)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_create_edge_annotations(G, pos): # noqa: N803
|
|
18
|
+
annotations, shapes = _create_edge_annotations(G, pos)
|
|
19
|
+
|
|
20
|
+
n_edges = len(G.edges())
|
|
21
|
+
assert len(annotations) == n_edges
|
|
22
|
+
assert len(shapes) == n_edges
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.parametrize("layout", [nx.shell_layout, nx.spring_layout])
|
|
26
|
+
@pytest.mark.parametrize("title", ["Causal Graph", "My Causal Graph"])
|
|
27
|
+
@pytest.mark.parametrize("subtitle", ["A subtitle", None])
|
|
28
|
+
def test_plot_graph(G, layout, title, subtitle): # noqa: N803
|
|
29
|
+
fig = plot_graph(G, layout=layout, title=title, subtitle=subtitle)
|
|
30
|
+
|
|
31
|
+
assert fig.layout.title["text"] == title
|
|
32
|
+
if subtitle is not None:
|
|
33
|
+
assert fig.layout.title["subtitle"]["text"] == subtitle
|
|
34
|
+
|
|
35
|
+
assert len(fig.data[-1].x) == len(G.nodes())
|
howso/visuals/tests/test_plot.py
CHANGED
|
@@ -37,9 +37,7 @@ def test_plot_interpretable_prediction_react(
|
|
|
37
37
|
react = iris_trainee.react(
|
|
38
38
|
action_features=[action_feature],
|
|
39
39
|
contexts=predict_case[context_features],
|
|
40
|
-
details={
|
|
41
|
-
"influential_cases": True
|
|
42
|
-
},
|
|
40
|
+
details={"influential_cases": True},
|
|
43
41
|
)
|
|
44
42
|
|
|
45
43
|
if do_actual_value:
|
|
@@ -62,7 +60,9 @@ def test_plot_interpretable_prediction_react(
|
|
|
62
60
|
generative_reacts = None
|
|
63
61
|
|
|
64
62
|
if do_residual:
|
|
65
|
-
residual = iris_trainee.get_prediction_stats(
|
|
63
|
+
residual = iris_trainee.get_prediction_stats(
|
|
64
|
+
details={"prediction_stats": True, "selected_prediction_stats": ["mae"]}
|
|
65
|
+
)
|
|
66
66
|
residual = residual[action_feature].iloc[0]
|
|
67
67
|
else:
|
|
68
68
|
residual = None
|
|
@@ -125,9 +125,7 @@ def test_plot_dataset(
|
|
|
125
125
|
if do_boundary_cases and highlight_cases is not None:
|
|
126
126
|
context_features = iris_features.get_names(without=["target"])
|
|
127
127
|
boundary_cases = iris_trainee.react(
|
|
128
|
-
contexts=highlight_cases[context_features],
|
|
129
|
-
action_features=["target"],
|
|
130
|
-
details={"boundary_cases": True}
|
|
128
|
+
contexts=highlight_cases[context_features], action_features=["target"], details={"boundary_cases": True}
|
|
131
129
|
)
|
|
132
130
|
boundary_cases = pd.concat(
|
|
133
131
|
[pd.DataFrame(bcs) for bcs in boundary_cases["details"]["boundary_cases"]]
|
|
@@ -141,7 +139,9 @@ def test_plot_dataset(
|
|
|
141
139
|
num_expected_traces += 1
|
|
142
140
|
|
|
143
141
|
fig = plot_dataset(
|
|
144
|
-
iris_test,
|
|
142
|
+
iris_test,
|
|
143
|
+
x,
|
|
144
|
+
y,
|
|
145
145
|
boundary_cases=boundary_cases,
|
|
146
146
|
most_similar_cases=most_similar_cases,
|
|
147
147
|
highlight_index=highlight_index,
|
|
@@ -157,12 +157,16 @@ def outliers_convictions(iris_trainee, iris_features):
|
|
|
157
157
|
iris_trainee.react_into_features(familiarity_conviction_addition=True, distance_contribution=True)
|
|
158
158
|
outliers = iris_trainee.get_cases(
|
|
159
159
|
session=iris_trainee.active_session,
|
|
160
|
-
features=
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
features=[
|
|
161
|
+
*iris_features.get_names(),
|
|
162
|
+
"familiarity_conviction_addition",
|
|
163
|
+
".session_training_index",
|
|
164
|
+
".session",
|
|
165
|
+
"distance_contribution",
|
|
166
|
+
],
|
|
163
167
|
)
|
|
164
168
|
|
|
165
|
-
outliers_indices = outliers[[
|
|
169
|
+
outliers_indices = outliers[[".session", ".session_training_index"]].values
|
|
166
170
|
convictions = iris_trainee.react(
|
|
167
171
|
case_indices=outliers_indices,
|
|
168
172
|
preserve_feature_values=iris_features.get_names(),
|
|
@@ -171,20 +175,15 @@ def outliers_convictions(iris_trainee, iris_features):
|
|
|
171
175
|
"boundary_cases": True,
|
|
172
176
|
"influential_cases": True,
|
|
173
177
|
"feature_full_residual_convictions_for_case": True,
|
|
174
|
-
}
|
|
175
|
-
)
|
|
176
|
-
convictions = pd.DataFrame(
|
|
177
|
-
convictions["details"]["feature_full_residual_convictions_for_case"]
|
|
178
|
+
},
|
|
178
179
|
)
|
|
180
|
+
convictions = pd.DataFrame(convictions["details"]["feature_full_residual_convictions_for_case"])
|
|
179
181
|
|
|
180
|
-
|
|
182
|
+
return outliers, convictions
|
|
181
183
|
|
|
182
184
|
|
|
183
185
|
@pytest.mark.parametrize("num_cases_to_plot", [1, 5, 10])
|
|
184
|
-
def test_plot_anomalies(
|
|
185
|
-
outliers_convictions,
|
|
186
|
-
num_cases_to_plot
|
|
187
|
-
):
|
|
186
|
+
def test_plot_anomalies(outliers_convictions, num_cases_to_plot):
|
|
188
187
|
outliers, convictions = outliers_convictions
|
|
189
188
|
fig = plot_anomalies(outliers, convictions, num_cases_to_plot=num_cases_to_plot)
|
|
190
189
|
assert len(fig.data[0].y) == num_cases_to_plot
|
|
@@ -223,11 +222,11 @@ def test_plot_feature_importances(feature_residuals):
|
|
|
223
222
|
@pytest.mark.parametrize("x_tickangle", [True, False, 45])
|
|
224
223
|
def test_plot_fairness_disparity(x_tickangle):
|
|
225
224
|
fairness_results = {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
"Dataset1": {"Male": 0.8, "Female": 0.7, "Other": 0.9},
|
|
226
|
+
"Dataset2": {"Male": 0.6, "Female": 0.9, "Other": 0.5},
|
|
227
|
+
"Dataset3": {"Male": 0.7, "Female": 0.4, "Other": 0.6},
|
|
229
228
|
}
|
|
230
|
-
fig = plot_fairness_disparity(fairness_results, reference_class=
|
|
229
|
+
fig = plot_fairness_disparity(fairness_results, reference_class="Male", x_tickangle=x_tickangle)
|
|
231
230
|
|
|
232
231
|
assert fig is not None
|
|
233
232
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: howso-visuals
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: Visualization utilities for use with Howso Engine.
|
|
5
5
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
6
6
|
Version 3, 19 November 2007
|
|
@@ -675,7 +675,8 @@ Requires-Python: >=3.10
|
|
|
675
675
|
Description-Content-Type: text/markdown
|
|
676
676
|
License-File: LICENSE-3RD-PARTY.txt
|
|
677
677
|
License-File: LICENSE.txt
|
|
678
|
-
Requires-Dist: howso-engine
|
|
678
|
+
Requires-Dist: howso-engine>=42.0
|
|
679
|
+
Requires-Dist: networkx
|
|
679
680
|
Requires-Dist: plotly[kaleido]~=6.0
|
|
680
681
|
Requires-Dist: scipy
|
|
681
682
|
Requires-Dist: seaborn
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
bin/build.sh,sha256=NUvva4qCMEfYKYGP6_Hxc5f1gItZ_hTJw9NBJjB396E,274
|
|
2
|
+
config/latest-mt-debug-howso.yml,sha256=sUdffc_XSiJZNRoovCYARZ2rQrSzMScNNK2M1uyTA-s,225
|
|
3
|
+
config/latest-mt-howso.yml,sha256=hB6fKQ3_ys_URygFUKl7fiL2vgMZwmpzWU7uwKHzN5E,144
|
|
4
|
+
config/latest-mt-noavx-debug-howso.yml,sha256=x0JuKpy0JzwVeeNsLRYbOo5BVVZnYUCI-ky9Kdqmis4,231
|
|
5
|
+
config/latest-st-debug-howso.yml,sha256=2eZm__DtD3-uszwjRA5ABE6h6gQznSca0-c7Zc_bIGs,226
|
|
6
|
+
config/latest-st-howso.yml,sha256=gfi7VNoAJ8QWh6eVlffks_QLPEYsnoUX7wS6UNx_nKc,145
|
|
7
|
+
config/powershell/Download-Tzdata.ps1,sha256=uGNszw3t3quz1ClN3PWlPr4cKMar9KxxFf4Ws8_JdrM,1505
|
|
8
|
+
config/powershell/Helper-Functions.ps1,sha256=oLEunSYLr-zxtG9kqYuOGG8v3kSxTQEpqeERWQ4jC8I,990
|
|
9
|
+
howso/visuals/__init__.py,sha256=OL9LT4186YIXkEmM4qc21maRnfrtxBmFUHnalcKzGWA,507
|
|
10
|
+
howso/visuals/colors.py,sha256=2ChjT4MUjA4ZqITR_K1j3fUKNRBd8M9iyJ4ZT10cNlw,1709
|
|
11
|
+
howso/visuals/graph.py,sha256=DvBx28IER95HRTEuowuBo1aWWPS7wx3KWrvPZejRnlo,6661
|
|
12
|
+
howso/visuals/visuals.py,sha256=fElgT6lc4KWG9qCY-mUqNL3gsZwcb56YUZJL_QUuMto,30409
|
|
13
|
+
howso/visuals/data/iris.csv,sha256=73iTb6rB42LgZwf89er-tEbuyjlvEAx6WywMPwt0GjU,2757
|
|
14
|
+
howso/visuals/tests/conftest.py,sha256=BcvCVDWbwaQKSstzJzN9G48KoDnCgTtVdgYo2CJZTWM,1293
|
|
15
|
+
howso/visuals/tests/test_graph.py,sha256=gfuJNpsNBLx2tDXDIR-ClbCZUSOQCmk8Dx2X-NhN2yM,1014
|
|
16
|
+
howso/visuals/tests/test_plot.py,sha256=M0YYqDzY4GYmDXcak2QUWn9Zehr5u8pR0SqhxiCUDbY,8111
|
|
17
|
+
howso_visuals-2.1.1.dist-info/licenses/LICENSE-3RD-PARTY.txt,sha256=IZ0jE6Q4mRGPplwo7uW_bQcxm-jBhe8Ol5s-sNphxnw,364089
|
|
18
|
+
howso_visuals-2.1.1.dist-info/licenses/LICENSE.txt,sha256=2xqHuoHohba7gpcZZKtOICRjzeKsQANXG8WoV9V35KM,33893
|
|
19
|
+
howso_visuals-2.1.1.dist-info/METADATA,sha256=OyjRrxKbeK4Iel2raDM2_1j9hcgMzfXY8d2Vw6_joT8,41051
|
|
20
|
+
howso_visuals-2.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
howso_visuals-2.1.1.dist-info/top_level.txt,sha256=4ltSHx7mNsXczuoCPkz1irjq1x1JZir2QrX-ZwRNWXU,22
|
|
22
|
+
howso_visuals-2.1.1.dist-info/RECORD,,
|
{howso_visuals-2.0.10.dist-info → howso_visuals-2.1.1.dist-info}/licenses/LICENSE-3RD-PARTY.txt
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Faker
|
|
2
|
-
37.
|
|
2
|
+
37.6.0
|
|
3
3
|
MIT License
|
|
4
4
|
joke2k
|
|
5
5
|
https://github.com/joke2k/faker
|
|
6
6
|
Faker is a Python package that generates fake data for you.
|
|
7
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/faker-37.
|
|
7
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/faker-37.6.0.dist-info/licenses/LICENSE.txt
|
|
8
8
|
Copyright (c) 2012 Daniele Faraglia
|
|
9
9
|
|
|
10
10
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -243,12 +243,12 @@ SOFTWARE.
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
choreographer
|
|
246
|
-
1.0.
|
|
246
|
+
1.0.10
|
|
247
247
|
UNKNOWN
|
|
248
248
|
Andrew Pikul <ajpikul@gmail.com>, Neyberson Atencio <neyberatencio@gmail.com>
|
|
249
249
|
https://github.com/plotly/choreographer
|
|
250
250
|
Devtools Protocol implementation for chrome.
|
|
251
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/choreographer-1.0.
|
|
251
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/choreographer-1.0.10.dist-info/licenses/LICENSE.md
|
|
252
252
|
# MIT License
|
|
253
253
|
|
|
254
254
|
Copyright (c) Plotly, Inc.
|
|
@@ -608,12 +608,12 @@ A library to handle automated deprecations
|
|
|
608
608
|
|
|
609
609
|
|
|
610
610
|
fonttools
|
|
611
|
-
4.59.
|
|
611
|
+
4.59.2
|
|
612
612
|
MIT
|
|
613
613
|
Just van Rossum
|
|
614
614
|
http://github.com/fonttools/fonttools
|
|
615
615
|
Tools to manipulate font files
|
|
616
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/fonttools-4.59.
|
|
616
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/fonttools-4.59.2.dist-info/licenses/LICENSE
|
|
617
617
|
MIT License
|
|
618
618
|
|
|
619
619
|
Copyright (c) 2017 Just van Rossum
|
|
@@ -638,12 +638,12 @@ SOFTWARE.
|
|
|
638
638
|
|
|
639
639
|
|
|
640
640
|
humanize
|
|
641
|
-
4.
|
|
641
|
+
4.13.0
|
|
642
642
|
UNKNOWN
|
|
643
643
|
Jason Moiron <jmoiron@jmoiron.net>
|
|
644
644
|
https://github.com/python-humanize/humanize
|
|
645
645
|
Python humanize utilities
|
|
646
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/humanize-4.
|
|
646
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/humanize-4.13.0.dist-info/licenses/LICENCE
|
|
647
647
|
Copyright (c) 2010-2020 Jason Moiron and Contributors
|
|
648
648
|
|
|
649
649
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
@@ -707,12 +707,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
707
707
|
|
|
708
708
|
|
|
709
709
|
joblib
|
|
710
|
-
1.5.
|
|
710
|
+
1.5.2
|
|
711
711
|
BSD License
|
|
712
712
|
Gael Varoquaux <gael.varoquaux@normalesup.org>
|
|
713
713
|
https://joblib.readthedocs.io
|
|
714
714
|
Lightweight pipelining with Python functions
|
|
715
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/joblib-1.5.
|
|
715
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/joblib-1.5.2.dist-info/licenses/LICENSE.txt
|
|
716
716
|
BSD 3-Clause License
|
|
717
717
|
|
|
718
718
|
Copyright (c) 2008-2021, The joblib developers.
|
|
@@ -1160,12 +1160,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
1160
1160
|
SOFTWARE.
|
|
1161
1161
|
|
|
1162
1162
|
narwhals
|
|
1163
|
-
2.
|
|
1163
|
+
2.2.0
|
|
1164
1164
|
MIT License
|
|
1165
1165
|
Marco Gorelli <hello_narwhals@proton.me>
|
|
1166
1166
|
https://github.com/narwhals-dev/narwhals
|
|
1167
1167
|
Extremely lightweight compatibility layer between dataframe libraries
|
|
1168
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/narwhals-2.
|
|
1168
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/narwhals-2.2.0.dist-info/licenses/LICENSE.md
|
|
1169
1169
|
MIT License
|
|
1170
1170
|
|
|
1171
1171
|
Copyright (c) 2024, Marco Gorelli
|
|
@@ -1189,6 +1189,52 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
1189
1189
|
SOFTWARE.
|
|
1190
1190
|
|
|
1191
1191
|
|
|
1192
|
+
networkx
|
|
1193
|
+
3.5
|
|
1194
|
+
BSD License
|
|
1195
|
+
Aric Hagberg <hagberg@lanl.gov>
|
|
1196
|
+
https://networkx.org/
|
|
1197
|
+
Python package for creating and manipulating graphs and networks
|
|
1198
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/networkx-3.5.dist-info/licenses/LICENSE.txt
|
|
1199
|
+
NetworkX is distributed with the 3-clause BSD license.
|
|
1200
|
+
|
|
1201
|
+
::
|
|
1202
|
+
|
|
1203
|
+
Copyright (c) 2004-2025, NetworkX Developers
|
|
1204
|
+
Aric Hagberg <hagberg@lanl.gov>
|
|
1205
|
+
Dan Schult <dschult@colgate.edu>
|
|
1206
|
+
Pieter Swart <swart@lanl.gov>
|
|
1207
|
+
All rights reserved.
|
|
1208
|
+
|
|
1209
|
+
Redistribution and use in source and binary forms, with or without
|
|
1210
|
+
modification, are permitted provided that the following conditions are
|
|
1211
|
+
met:
|
|
1212
|
+
|
|
1213
|
+
* Redistributions of source code must retain the above copyright
|
|
1214
|
+
notice, this list of conditions and the following disclaimer.
|
|
1215
|
+
|
|
1216
|
+
* Redistributions in binary form must reproduce the above
|
|
1217
|
+
copyright notice, this list of conditions and the following
|
|
1218
|
+
disclaimer in the documentation and/or other materials provided
|
|
1219
|
+
with the distribution.
|
|
1220
|
+
|
|
1221
|
+
* Neither the name of the NetworkX Developers nor the names of its
|
|
1222
|
+
contributors may be used to endorse or promote products derived
|
|
1223
|
+
from this software without specific prior written permission.
|
|
1224
|
+
|
|
1225
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
1226
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
1227
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
1228
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
1229
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
1230
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
1231
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
1232
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
1233
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
1234
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1235
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1236
|
+
|
|
1237
|
+
|
|
1192
1238
|
numba
|
|
1193
1239
|
0.61.2
|
|
1194
1240
|
BSD License
|
|
@@ -2203,12 +2249,12 @@ License: LGPL-2.1-or-later
|
|
|
2203
2249
|
|
|
2204
2250
|
|
|
2205
2251
|
orjson
|
|
2206
|
-
3.11.
|
|
2252
|
+
3.11.3
|
|
2207
2253
|
Apache Software License; MIT License
|
|
2208
2254
|
UNKNOWN
|
|
2209
2255
|
https://github.com/ijl/orjson
|
|
2210
|
-
|
|
2211
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/orjson-3.11.
|
|
2256
|
+
Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy
|
|
2257
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/orjson-3.11.3.dist-info/licenses/LICENSE-APACHE
|
|
2212
2258
|
Apache License
|
|
2213
2259
|
Version 2.0, January 2004
|
|
2214
2260
|
http://www.apache.org/licenses/
|
|
@@ -2425,12 +2471,12 @@ under the terms of *both* these licenses.
|
|
|
2425
2471
|
|
|
2426
2472
|
|
|
2427
2473
|
pandas
|
|
2428
|
-
2.3.
|
|
2474
|
+
2.3.2
|
|
2429
2475
|
BSD License
|
|
2430
2476
|
The Pandas Development Team <pandas-dev@python.org>
|
|
2431
2477
|
https://pandas.pydata.org
|
|
2432
2478
|
Powerful data structures for data analysis, time series, and statistics
|
|
2433
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/pandas-2.3.
|
|
2479
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/pandas-2.3.2.dist-info/LICENSE
|
|
2434
2480
|
BSD 3-Clause License
|
|
2435
2481
|
|
|
2436
2482
|
Copyright (c) 2008-2011, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
|
|
@@ -7011,12 +7057,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
7011
7057
|
|
|
7012
7058
|
|
|
7013
7059
|
typing_extensions
|
|
7014
|
-
4.
|
|
7060
|
+
4.15.0
|
|
7015
7061
|
UNKNOWN
|
|
7016
7062
|
"Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee" <levkivskyi@gmail.com>
|
|
7017
7063
|
https://github.com/python/typing_extensions
|
|
7018
7064
|
Backported and Experimental Type Hints for Python 3.9+
|
|
7019
|
-
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/typing_extensions-4.
|
|
7065
|
+
/home/runner/.pyenv/versions/3.13.7/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/licenses/LICENSE
|
|
7020
7066
|
A. HISTORY OF THE SOFTWARE
|
|
7021
7067
|
==========================
|
|
7022
7068
|
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
bin/build.sh,sha256=NUvva4qCMEfYKYGP6_Hxc5f1gItZ_hTJw9NBJjB396E,274
|
|
2
|
-
config/latest-mt-debug-howso.yml,sha256=sUdffc_XSiJZNRoovCYARZ2rQrSzMScNNK2M1uyTA-s,225
|
|
3
|
-
config/latest-mt-howso.yml,sha256=hB6fKQ3_ys_URygFUKl7fiL2vgMZwmpzWU7uwKHzN5E,144
|
|
4
|
-
config/latest-mt-noavx-debug-howso.yml,sha256=x0JuKpy0JzwVeeNsLRYbOo5BVVZnYUCI-ky9Kdqmis4,231
|
|
5
|
-
config/latest-st-debug-howso.yml,sha256=2eZm__DtD3-uszwjRA5ABE6h6gQznSca0-c7Zc_bIGs,226
|
|
6
|
-
config/latest-st-howso.yml,sha256=gfi7VNoAJ8QWh6eVlffks_QLPEYsnoUX7wS6UNx_nKc,145
|
|
7
|
-
config/powershell/Download-Tzdata.ps1,sha256=uGNszw3t3quz1ClN3PWlPr4cKMar9KxxFf4Ws8_JdrM,1505
|
|
8
|
-
config/powershell/Helper-Functions.ps1,sha256=oLEunSYLr-zxtG9kqYuOGG8v3kSxTQEpqeERWQ4jC8I,990
|
|
9
|
-
howso/visuals/__init__.py,sha256=n6lBHs39jLo1n46-8o8-cI2G-eHSeX5vNSK3fjbGZ_s,474
|
|
10
|
-
howso/visuals/colors.py,sha256=2ChjT4MUjA4ZqITR_K1j3fUKNRBd8M9iyJ4ZT10cNlw,1709
|
|
11
|
-
howso/visuals/visuals.py,sha256=fElgT6lc4KWG9qCY-mUqNL3gsZwcb56YUZJL_QUuMto,30409
|
|
12
|
-
howso/visuals/data/iris.csv,sha256=73iTb6rB42LgZwf89er-tEbuyjlvEAx6WywMPwt0GjU,2757
|
|
13
|
-
howso/visuals/tests/conftest.py,sha256=bV0s_LxtJJIzFOUuSI3ybHZIocG6RGP3vHF5V9Qdlh4,1359
|
|
14
|
-
howso/visuals/tests/test_plot.py,sha256=W1KQMN3MIeLuTXCIDIZtZBTlIjL-k1wBQ4aKqq42fYo,8090
|
|
15
|
-
howso_visuals-2.0.10.dist-info/licenses/LICENSE-3RD-PARTY.txt,sha256=gTrRPD9wYv4ZDA9rQ6o-m_bPglAJkYi2LYw1BnADGFQ,361998
|
|
16
|
-
howso_visuals-2.0.10.dist-info/licenses/LICENSE.txt,sha256=2xqHuoHohba7gpcZZKtOICRjzeKsQANXG8WoV9V35KM,33893
|
|
17
|
-
howso_visuals-2.0.10.dist-info/METADATA,sha256=bMTzH8pui3c4Yrap6XoqT9YzO7ut6v1yQUrZFvwkGPY,41028
|
|
18
|
-
howso_visuals-2.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
-
howso_visuals-2.0.10.dist-info/top_level.txt,sha256=4ltSHx7mNsXczuoCPkz1irjq1x1JZir2QrX-ZwRNWXU,22
|
|
20
|
-
howso_visuals-2.0.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|