From bed9b23908d3a7bb3ae128ae06aa574d84db0fdc Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Mon, 6 Jul 2020 17:12:07 -0500 Subject: [PATCH 01/27] Refine `plot_relations()` Added keyword arguments to control plot properties, added separate mechanism labels, changed default values --- pyphi/visualize.py | 61 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 740048f03..8122474d0 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -92,7 +92,14 @@ def plot_relations( relations, max_order=3, cause_effect_offset=(0.5, 0, 0), - vertex_size_range=(10, 30), + vertex_size_range=(10,20), + plot_dimentions=(800,1200), + mechanism_labels_size=10, + purview_labels_size=7.5, + mesh_opacity=0.2, + show_mechanism_labels=True, + show_purview_labels=True, + show_mesh=True, ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -130,25 +137,57 @@ def plot_relations( # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extract vertex indices for plotly x, y, z = coords[:, 0], coords[:, 1], coords[:, 2] + # Get mechanism and purview labels - mechanism_labels = list(map(label_mechanism, separated_ces)) + mechanism_labels = list(map(label_mechanism, ces)) + mechanism_labels_x2 = list(map(label_mechanism, separated_ces)) purview_labels = list(map(label_purview, separated_ces)) - # Make the labels - labels = go.Scatter3d( - x=x, y=y, z=z, mode="text", text=purview_labels, name="Labels", showlegend=True, + + # Make mechanism labels + xm, ym, zm = [c + cause_effect_offset[0]/2 for c in x[::2]], y[::2], z[::2] + mech_labels = go.Scatter3d( + x=xm, + y=ym, + z=zm, + visible=show_mechanism_labels, + mode="text", + text=mechanism_labels, + name="Mechanism Labels", + showlegend=True, + textfont=dict(size=mechanism_labels_size,color='black'), + hoverinfo='skip', ) - figure_data.append(labels) - # Compute size and color - size = vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces) + figure_data.append(mech_labels) + + # Make purview labels color = list(flatten([("red", "green")] * len(ces))) + purv_labels = go.Scatter3d( + visible=show_purview_labels, + x=x, + y=y, + z=z, + mode="text", + text=purview_labels, + name="Purview Labels", + showlegend=True, + textfont=dict(size=purview_labels_size,color=color), + hoverinfo='skip', + ) + figure_data.append(purv_labels) + # Compute size and color + size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) vertices = go.Scatter3d( x=x, y=y, z=z, mode="markers", name="Purviews", + text=purview_labels, showlegend=True, marker=dict(size=size, color=color), + hoverinfo="text", + hovertext=purview_labels, + hoverlabel=dict(bgcolor=color), ) figure_data.append(vertices) @@ -188,6 +227,7 @@ def plot_relations( # Extract triangle indices i, j, k = zip(*triangles) mesh = go.Mesh3d( + visible=show_mesh, # x, y, and z are the coordinates of vertices x=x, y=y, @@ -198,11 +238,12 @@ def plot_relations( k=k, # Intensity of each vertex, which will be interpolated and color-coded intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=0.2, + opacity=mesh_opacity, colorscale="viridis", showscale=False, name="3-Relations", showlegend=True, + hoverinfo='skip', ) figure_data.append(mesh) @@ -226,6 +267,8 @@ def plot_relations( hovermode="closest", title="", autosize=True, + height=plot_dimentions[0], + width=plot_dimentions[1] ) # Merge figures return go.Figure(data=figure_data, layout=layout) From 7e8c522e8e1162f9a253b2503164c574e37cf01f Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Mon, 6 Jul 2020 21:54:02 -0500 Subject: [PATCH 02/27] Updated visualize.py Added hoverinfo functions for mechanism labels and vertices, added "title" keyword argument, implemented cosmetic changes to code --- pyphi/visualize.py | 71 ++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 8122474d0..3cd9608cf 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -78,6 +78,14 @@ def label_purview(mice): return make_label(mice.purview, node_labels=mice.node_labels) +def hovertext_mechanism(distinction): + return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {distinction.cause.phi}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {distinction.effect.phi}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" + + +def hovertext_purview(mice): + return f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}" + + def vertex_sizes(min_size, max_size, ces): phis = np.array( [(distinction.cause.phi, distinction.effect.phi) for distinction in ces] @@ -92,14 +100,15 @@ def plot_relations( relations, max_order=3, cause_effect_offset=(0.5, 0, 0), - vertex_size_range=(10,20), - plot_dimentions=(800,1200), + vertex_size_range=(10, 20), + plot_dimentions=(800, 1200), mechanism_labels_size=10, - purview_labels_size=7.5, + purview_labels_size=7.5, mesh_opacity=0.2, show_mechanism_labels=True, - show_purview_labels=True, + show_purview_labels=True, show_mesh=True, + title="", ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -140,11 +149,15 @@ def plot_relations( # Get mechanism and purview labels mechanism_labels = list(map(label_mechanism, ces)) - mechanism_labels_x2 = list(map(label_mechanism, separated_ces)) + mechanism_labels_x2 = list(map(label_mechanism, separated_ces)) purview_labels = list(map(label_purview, separated_ces)) - + + mechanism_hovertext = list(map(hovertext_mechanism, ces)) + vertices_hovertext = list(map(hovertext_purview, separated_ces)) + # Make mechanism labels - xm, ym, zm = [c + cause_effect_offset[0]/2 for c in x[::2]], y[::2], z[::2] + xm, ym, zm = [c + cause_effect_offset[0] + / 2 for c in x[::2]], y[::2], z[::2] mech_labels = go.Scatter3d( x=xm, y=ym, @@ -154,10 +167,12 @@ def plot_relations( text=mechanism_labels, name="Mechanism Labels", showlegend=True, - textfont=dict(size=mechanism_labels_size,color='black'), - hoverinfo='skip', + textfont=dict(size=mechanism_labels_size, color="black"), + hoverinfo="text", + hovertext=mechanism_hovertext, + hoverlabel=dict(bgcolor="white"), ) - figure_data.append(mech_labels) + figure_data.append(mech_labels) # Make purview labels color = list(flatten([("red", "green")] * len(ces))) @@ -166,28 +181,31 @@ def plot_relations( x=x, y=y, z=z, - mode="text", - text=purview_labels, - name="Purview Labels", - showlegend=True, - textfont=dict(size=purview_labels_size,color=color), - hoverinfo='skip', + mode="text", + text=purview_labels, + name="Purview Labels", + showlegend=True, + textfont=dict(size=purview_labels_size, color=color), + hoverinfo="skip", ) figure_data.append(purv_labels) # Compute size and color - size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) + size = list(flatten(vertex_sizes( + vertex_size_range[0], vertex_size_range[1], ces))) + purview_phis = [purview.phi for purview in separated_ces] + direction_labels = list(flatten([["Cause", "Effect"] for c in ces])) vertices = go.Scatter3d( x=x, y=y, z=z, mode="markers", name="Purviews", - text=purview_labels, + text=purview_labels, showlegend=True, marker=dict(size=size, color=color), hoverinfo="text", - hovertext=purview_labels, - hoverlabel=dict(bgcolor=color), + hovertext=vertices_hovertext, + hoverlabel=dict(bgcolor=color), ) figure_data.append(vertices) @@ -208,11 +226,13 @@ def plot_relations( x=x[edges], y=y[edges], z=z[edges], - line_group=flatten(zip(range(len(edges) // 2), range(len(edges) // 2))), + line_group=flatten( + zip(range(len(edges) // 2), range(len(edges) // 2))), ) ) # Plot edges - edge_figure = px.line_3d(edges, x="x", y="y", z="z", line_group="line_group") + edge_figure = px.line_3d( + edges, x="x", y="y", z="z", line_group="line_group") figure_data.extend(edge_figure.data) # 3-relations @@ -243,7 +263,7 @@ def plot_relations( showscale=False, name="3-Relations", showlegend=True, - hoverinfo='skip', + hoverinfo="skip", ) figure_data.append(mesh) @@ -265,10 +285,11 @@ def plot_relations( showlegend=True, scene=dict(xaxis=dict(axis), yaxis=dict(axis), zaxis=dict(axis)), hovermode="closest", - title="", + title=title, + legend=dict(title=dict(text="Trace legend (click trace to show/hide):",font=dict(color='black',size=15))), autosize=True, height=plot_dimentions[0], - width=plot_dimentions[1] + width=plot_dimentions[1] ) # Merge figures return go.Figure(data=figure_data, layout=layout) From 64b69e5cc4a73c71dcf2e17d74fbaf699d30b267 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Tue, 7 Jul 2020 23:01:47 -0500 Subject: [PATCH 03/27] Update visualize.py Formatted code with black --- pyphi/visualize.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 3cd9608cf..091a529c3 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -156,8 +156,7 @@ def plot_relations( vertices_hovertext = list(map(hovertext_purview, separated_ces)) # Make mechanism labels - xm, ym, zm = [c + cause_effect_offset[0] - / 2 for c in x[::2]], y[::2], z[::2] + xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], z[::2] mech_labels = go.Scatter3d( x=xm, y=ym, @@ -190,8 +189,7 @@ def plot_relations( ) figure_data.append(purv_labels) # Compute size and color - size = list(flatten(vertex_sizes( - vertex_size_range[0], vertex_size_range[1], ces))) + size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) purview_phis = [purview.phi for purview in separated_ces] direction_labels = list(flatten([["Cause", "Effect"] for c in ces])) vertices = go.Scatter3d( @@ -226,13 +224,11 @@ def plot_relations( x=x[edges], y=y[edges], z=z[edges], - line_group=flatten( - zip(range(len(edges) // 2), range(len(edges) // 2))), + line_group=flatten(zip(range(len(edges) // 2), range(len(edges) // 2))), ) ) # Plot edges - edge_figure = px.line_3d( - edges, x="x", y="y", z="z", line_group="line_group") + edge_figure = px.line_3d(edges, x="x", y="y", z="z", line_group="line_group") figure_data.extend(edge_figure.data) # 3-relations @@ -286,10 +282,15 @@ def plot_relations( scene=dict(xaxis=dict(axis), yaxis=dict(axis), zaxis=dict(axis)), hovermode="closest", title=title, - legend=dict(title=dict(text="Trace legend (click trace to show/hide):",font=dict(color='black',size=15))), + legend=dict( + title=dict( + text="Trace legend (click trace to show/hide):", + font=dict(color="black", size=15), + ) + ), autosize=True, height=plot_dimentions[0], - width=plot_dimentions[1] + width=plot_dimentions[1], ) # Merge figures return go.Figure(data=figure_data, layout=layout) From 745c1f4259639fc756be4daf867953a8b3007d5f Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Tue, 7 Jul 2020 23:07:16 -0500 Subject: [PATCH 04/27] Refined `plot_relations` Substituted `edge_figure` (generated with px.line3d() function) with `edges_trace`(generated with go.Scatter3d() function) for consistency with other trace generation and possibility to manipulate trace. --- pyphi/visualize.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 091a529c3..643285344 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -228,8 +228,18 @@ def plot_relations( ) ) # Plot edges - edge_figure = px.line_3d(edges, x="x", y="y", z="z", line_group="line_group") - figure_data.extend(edge_figure.data) + edges_trace = go.Scatter3d( + x=edges["x"], + y=edges["y"], + z=edges["z"], + mode="lines", + name="2-Relations", + line_width=0.5, + line_color="blue", + showlegend=True, + hoverinfo="skip", + ) + figure_data.append(edges_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9207d010e093d0fdce3e7211a6c898f7c144af70 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Tue, 7 Jul 2020 23:13:49 -0500 Subject: [PATCH 05/27] Refined `plot_relations()` Substituted initialization of figure_data as list with initialization of figure as plotly figure object. Added traces and layout to figure with appropriate plotly function. --- pyphi/visualize.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 643285344..3d6724f99 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -115,8 +115,8 @@ def plot_relations( # Separate CES into causes and effects separated_ces = rel.separate_ces(ces) - # Initialize figure data - figure_data = [] + # Initialize figure + fig = go.Figure() # Dimensionality reduction # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -171,7 +171,7 @@ def plot_relations( hovertext=mechanism_hovertext, hoverlabel=dict(bgcolor="white"), ) - figure_data.append(mech_labels) + fig.add_trace(mech_labels) # Make purview labels color = list(flatten([("red", "green")] * len(ces))) @@ -187,7 +187,8 @@ def plot_relations( textfont=dict(size=purview_labels_size, color=color), hoverinfo="skip", ) - figure_data.append(purv_labels) + fig.add_trace(purv_labels) + # Compute size and color size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) purview_phis = [purview.phi for purview in separated_ces] @@ -205,7 +206,7 @@ def plot_relations( hovertext=vertices_hovertext, hoverlabel=dict(bgcolor=color), ) - figure_data.append(vertices) + fig.add_trace(vertices) # 2-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -239,7 +240,7 @@ def plot_relations( showlegend=True, hoverinfo="skip", ) - figure_data.append(edges_trace) + fig.add_trace(edges_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -271,7 +272,7 @@ def plot_relations( showlegend=True, hoverinfo="skip", ) - figure_data.append(mesh) + fig.add_trace(mesh) # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -302,5 +303,7 @@ def plot_relations( height=plot_dimentions[0], width=plot_dimentions[1], ) - # Merge figures - return go.Figure(data=figure_data, layout=layout) + # Apply layout + fig.layout = layout + + return fig From 4fe1d16554ad7cc9f718c7b2d541289ca388b501 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Wed, 8 Jul 2020 13:17:36 -0500 Subject: [PATCH 06/27] Update visualize.py Used magic underscore to define scene axes --- pyphi/visualize.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 3d6724f99..2822b818a 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -290,7 +290,9 @@ def plot_relations( ) layout = go.Layout( showlegend=True, - scene=dict(xaxis=dict(axis), yaxis=dict(axis), zaxis=dict(axis)), + scene_xaxis=axis, + scene_yaxis=axis, + scene_zaxis=axis, hovermode="closest", title=title, legend=dict( From 0ac278ac9c37140117b799e967e9adbb2a05e3c2 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Wed, 8 Jul 2020 13:25:00 -0500 Subject: [PATCH 07/27] Update visualize.py Added UMAP axes labels --- pyphi/visualize.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 2822b818a..01912868b 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -276,23 +276,27 @@ def plot_relations( # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - axis = dict( - showbackground=True, - showline=True, - zeroline=True, - showgrid=True, - gridcolor="lightgray", - showticklabels=False, - title="", - showspikes=True, - autorange=True, - backgroundcolor="white", - ) + axes = [ + dict( + showbackground=True, + showline=True, + zeroline=True, + showgrid=True, + gridcolor="lightgray", + showticklabels=False, + title=f"UMAP {dimension}", + showspikes=True, + autorange=True, + backgroundcolor="white", + ) + for dimension in range(1,4) + ] + layout = go.Layout( showlegend=True, - scene_xaxis=axis, - scene_yaxis=axis, - scene_zaxis=axis, + scene_xaxis=axes[0], + scene_yaxis=axes[1], + scene_zaxis=axes[2], hovermode="closest", title=title, legend=dict( @@ -307,5 +311,5 @@ def plot_relations( ) # Apply layout fig.layout = layout - + return fig From e6f887bd211ce17b0eb1cdf81a10d9a3078a5f71 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Wed, 8 Jul 2020 13:57:18 -0500 Subject: [PATCH 08/27] Refined `plot_ces()` Changed trace names --- pyphi/visualize.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 01912868b..b5bc74c86 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -157,7 +157,7 @@ def plot_relations( # Make mechanism labels xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], z[::2] - mech_labels = go.Scatter3d( + mechanism_labels_trace = go.Scatter3d( x=xm, y=ym, z=zm, @@ -171,11 +171,11 @@ def plot_relations( hovertext=mechanism_hovertext, hoverlabel=dict(bgcolor="white"), ) - fig.add_trace(mech_labels) + fig.add_trace(mechanism_labels_trace) # Make purview labels color = list(flatten([("red", "green")] * len(ces))) - purv_labels = go.Scatter3d( + purview_labels_trace = go.Scatter3d( visible=show_purview_labels, x=x, y=y, @@ -187,13 +187,13 @@ def plot_relations( textfont=dict(size=purview_labels_size, color=color), hoverinfo="skip", ) - fig.add_trace(purv_labels) + fig.add_trace(purview_labels_trace) # Compute size and color size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) purview_phis = [purview.phi for purview in separated_ces] direction_labels = list(flatten([["Cause", "Effect"] for c in ces])) - vertices = go.Scatter3d( + vertices_purviews_trace = go.Scatter3d( x=x, y=y, z=z, @@ -206,7 +206,7 @@ def plot_relations( hovertext=vertices_hovertext, hoverlabel=dict(bgcolor=color), ) - fig.add_trace(vertices) + fig.add_trace(vertices_purviews_trace) # 2-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -229,7 +229,7 @@ def plot_relations( ) ) # Plot edges - edges_trace = go.Scatter3d( + edges_2relations_trace = go.Scatter3d( x=edges["x"], y=edges["y"], z=edges["z"], @@ -240,7 +240,7 @@ def plot_relations( showlegend=True, hoverinfo="skip", ) - fig.add_trace(edges_trace) + fig.add_trace(edges_2relations_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -253,7 +253,7 @@ def plot_relations( if triangles: # Extract triangle indices i, j, k = zip(*triangles) - mesh = go.Mesh3d( + triangles_3relations_trace = go.Mesh3d( visible=show_mesh, # x, y, and z are the coordinates of vertices x=x, @@ -272,7 +272,7 @@ def plot_relations( showlegend=True, hoverinfo="skip", ) - fig.add_trace(mesh) + fig.add_trace(triangles_3relations_trace) # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 5faeeac3b25603cc66c0ebe6885a250d964ecfc3 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:10:53 -0500 Subject: [PATCH 09/27] Update visualize.py Modified vertex_sizes function to make it work for both mechanisms and purviews --- pyphi/visualize.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index b5bc74c86..cf70a5d9f 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -86,13 +86,13 @@ def hovertext_purview(mice): return f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}" -def vertex_sizes(min_size, max_size, ces): +def vertex_sizes(min_size, max_size, elements): phis = np.array( - [(distinction.cause.phi, distinction.effect.phi) for distinction in ces] + [element.phi for element in elements] ) min_phi = phis.min() max_phi = phis.max() - return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) + return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) def plot_relations( @@ -190,7 +190,7 @@ def plot_relations( fig.add_trace(purview_labels_trace) # Compute size and color - size = list(flatten(vertex_sizes(vertex_size_range[0], vertex_size_range[1], ces))) + purview_sizes = vertex_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) purview_phis = [purview.phi for purview in separated_ces] direction_labels = list(flatten([["Cause", "Effect"] for c in ces])) vertices_purviews_trace = go.Scatter3d( @@ -201,7 +201,7 @@ def plot_relations( name="Purviews", text=purview_labels, showlegend=True, - marker=dict(size=size, color=color), + marker=dict(size=purview_sizes, color=color), hoverinfo="text", hovertext=vertices_hovertext, hoverlabel=dict(bgcolor=color), From 6e7081182b122b2e9d7eb5dd7ab12c4d57bc12fb Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:15:09 -0500 Subject: [PATCH 10/27] Update visualize.py Added chunk_list function to chunk a list --- pyphi/visualize.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index cf70a5d9f..8b1c7835e 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -95,6 +95,12 @@ def vertex_sizes(min_size, max_size, elements): return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) +def chunk_list(my_list, n): + """Yield successive n-sized chunks from lst.""" + for i in range(0, len(my_list), n): + yield my_list[i:i + n] + + def plot_relations( ces, relations, From 5f6046cc9c5f9c5cf619a25260d70f275873a557 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:18:04 -0500 Subject: [PATCH 11/27] Update visualize.py Added keyword arguments to plot_relations function --- pyphi/visualize.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 8b1c7835e..ba41e017a 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -111,10 +111,16 @@ def plot_relations( mechanism_labels_size=10, purview_labels_size=7.5, mesh_opacity=0.2, + edge_width=1, show_mechanism_labels=True, show_purview_labels=True, + show_vertices_mechanisms=True, + show_vertices_purviews=True, + show_edges=True, show_mesh=True, + showgrid=False, title="", + eye_coordinates=(1.25,1.25,1.25), ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) From c1953526e00beb9900294ab206db08df89cddc90 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:19:53 -0500 Subject: [PATCH 12/27] Update visualize.py Modified axes and layout --- pyphi/visualize.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index ba41e017a..71a44f70c 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -288,20 +288,23 @@ def plot_relations( # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + axes_range = [(min(d)-1,max(d)+1) for d in (x,y,z)] + axes = [ dict( - showbackground=True, - showline=True, - zeroline=True, - showgrid=True, + showbackground=False, + showline=False, + zeroline=False, + showgrid=showgrid, gridcolor="lightgray", showticklabels=False, - title=f"UMAP {dimension}", showspikes=True, - autorange=True, + autorange=False, + range=axes_range[dimension], backgroundcolor="white", + title='', ) - for dimension in range(1,4) + for dimension in range(3) ] layout = go.Layout( @@ -309,6 +312,11 @@ def plot_relations( scene_xaxis=axes[0], scene_yaxis=axes[1], scene_zaxis=axes[2], + scene_camera=dict( + eye=dict( + x=eye_coordinates[0], y=eye_coordinates[1], z=eye_coordinates[2] + ) + ), hovermode="closest", title=title, legend=dict( @@ -321,6 +329,7 @@ def plot_relations( height=plot_dimentions[0], width=plot_dimentions[1], ) + # Apply layout fig.layout = layout From a6c5a531e79e262d521f032d37331bb3c4e98423 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:21:46 -0500 Subject: [PATCH 13/27] Update visualize.py Added renames labels_mechanisms_trace and added vertices_mechanisms_trace to show mechanisms as third marker between cause and effect vertices --- pyphi/visualize.py | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 71a44f70c..3e333e1ef 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -169,25 +169,44 @@ def plot_relations( # Make mechanism labels xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], z[::2] - mechanism_labels_trace = go.Scatter3d( + labels_mechanisms_trace = go.Scatter3d( + visible=show_mechanism_labels, x=xm, y=ym, z=zm, - visible=show_mechanism_labels, mode="text", text=mechanism_labels, name="Mechanism Labels", showlegend=True, textfont=dict(size=mechanism_labels_size, color="black"), + hoverinfo="skip", + ) + fig.add_trace(labels_mechanisms_trace) + + # Compute purview and mechanism marker sizes + purview_sizes = vertex_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) + mechanism_sizes = [min(phis) for phis in chunk_list(purview_sizes, 2)] + + # Make mechanisms trace + vertices_mechanisms_trace = go.Scatter3d( + visible=show_vertices_mechanisms, + x=xm, + y=ym, + z=zm, + mode="markers", + name="Mechanisms", + text=mechanism_labels, + showlegend=True, + marker=dict(size=mechanism_sizes, color='black'), hoverinfo="text", hovertext=mechanism_hovertext, hoverlabel=dict(bgcolor="white"), ) - fig.add_trace(mechanism_labels_trace) + fig.add_trace(vertices_mechanisms_trace) - # Make purview labels + # Make purview labels trace color = list(flatten([("red", "green")] * len(ces))) - purview_labels_trace = go.Scatter3d( + labels_purviews_trace = go.Scatter3d( visible=show_purview_labels, x=x, y=y, @@ -199,13 +218,13 @@ def plot_relations( textfont=dict(size=purview_labels_size, color=color), hoverinfo="skip", ) - fig.add_trace(purview_labels_trace) + fig.add_trace(labels_purviews_trace) - # Compute size and color - purview_sizes = vertex_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) + # Make purviews trace purview_phis = [purview.phi for purview in separated_ces] direction_labels = list(flatten([["Cause", "Effect"] for c in ces])) vertices_purviews_trace = go.Scatter3d( + visible=show_vertices_purviews, x=x, y=y, z=z, From 3568cf25093c987a5132558ed7758f64e90810ad Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 21:56:21 -0500 Subject: [PATCH 14/27] Update visualize.py Added functions label_state and label_two_relation --- pyphi/visualize.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 3e333e1ef..b4eebc52a 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -78,6 +78,21 @@ def label_purview(mice): return make_label(mice.purview, node_labels=mice.node_labels) +def label_state(mice): + """Return state of the purview""" + return [rel.maximal_state(mice)[0][node] for node in mice.purview] + + +def label_two_relation(relation): + """Return label text fora two relation in the form: + tuple(list(tuple(mechanism1, purview1, purview1_state), tuple(mechanism2, purview2, purview2_state)), list(relation_purview, relation_small_phi)) + """ + relata = relation.relata + relata_info = [(label_mechanism(relatum),label_purview(relatum), label_state(relatum)) for relatum in relata] + relation_info = [make_label(relation.purview,relation.subsystem.node_labels), relation.phi] + return relata_info, relation_info + + def hovertext_mechanism(distinction): return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {distinction.cause.phi}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {distinction.effect.phi}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" From c83f4a3b298576c4c70058e9571ad793cdc2978b Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 22:18:04 -0500 Subject: [PATCH 15/27] Update visualize.py Replaces label_two_relation() with hovertext_relation() --- pyphi/visualize.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index b4eebc52a..c5e1c24d6 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -83,16 +83,6 @@ def label_state(mice): return [rel.maximal_state(mice)[0][node] for node in mice.purview] -def label_two_relation(relation): - """Return label text fora two relation in the form: - tuple(list(tuple(mechanism1, purview1, purview1_state), tuple(mechanism2, purview2, purview2_state)), list(relation_purview, relation_small_phi)) - """ - relata = relation.relata - relata_info = [(label_mechanism(relatum),label_purview(relatum), label_state(relatum)) for relatum in relata] - relation_info = [make_label(relation.purview,relation.subsystem.node_labels), relation.phi] - return relata_info, relation_info - - def hovertext_mechanism(distinction): return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {distinction.cause.phi}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {distinction.effect.phi}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" @@ -101,6 +91,13 @@ def hovertext_purview(mice): return f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}" +def hovertext_relation(relation): + relata = relation.relata + relata_info = [str(f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}") for mice in relata] + relation_info = f"Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {relation.phi}" + return relata_info, relation_info + + def vertex_sizes(min_size, max_size, elements): phis = np.array( [element.phi for element in elements] From 93a194427819d3bbc4e97718f61f2a4662e9d495 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 22:48:55 -0500 Subject: [PATCH 16/27] Update visualize.py Added def label_relation() function --- pyphi/visualize.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index c5e1c24d6..288b8a9b1 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -83,6 +83,13 @@ def label_state(mice): return [rel.maximal_state(mice)[0][node] for node in mice.purview] +def label_relation(relation): + relata = relation.relata + relata_info = '
'.join([f"{label_mechanism(mice)}'s {mice.direction.name} = {label_purview(mice)}" for n,mice in enumerate(relata)]) + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {relation.phi}
" + return relata_info + relation_info + + def hovertext_mechanism(distinction): return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {distinction.cause.phi}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {distinction.effect.phi}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" From 619923c2cbea416cf498601f94e2349f314b78f5 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 23:31:52 -0500 Subject: [PATCH 17/27] Update visualize.py Edited label_relation() and hovertext_relation() functions --- pyphi/visualize.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 288b8a9b1..18e02d6d8 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -84,9 +84,12 @@ def label_state(mice): def label_relation(relation): - relata = relation.relata - relata_info = '
'.join([f"{label_mechanism(mice)}'s {mice.direction.name} = {label_purview(mice)}" for n,mice in enumerate(relata)]) - relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {relation.phi}
" + relata = relation.relata + + relata_info = '
'.join([f"{label_mechanism(mice)} / {label_purview(mice)} [{mice.direction.name}]" for n,mice in enumerate(relata)]) + + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {np.round(relation.phi,4)}
" + return relata_info + relation_info @@ -100,9 +103,13 @@ def hovertext_purview(mice): def hovertext_relation(relation): relata = relation.relata - relata_info = [str(f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}") for mice in relata] - relation_info = f"Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {relation.phi}" - return relata_info, relation_info + + relata_info = ''.join([f"
Distinction {n}: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}
" for n,mice in enumerate(relata)]) + + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {np.round(relation.phi,4)}
" + + return f"
={len(relata)}-Relation=
" + relata_info + relation_info + def vertex_sizes(min_size, max_size, elements): From 1e65540d25d6a826fc8625d47d88b0111f4467b1 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 23:34:53 -0500 Subject: [PATCH 18/27] Refined `plot_relations()` Added 2-relations (edges) as individual traces, added 2-relation hover labels, grouped all traces in a single legend-group to show/hide together --- pyphi/visualize.py | 71 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 18e02d6d8..d4f701cf2 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -79,7 +79,6 @@ def label_purview(mice): def label_state(mice): - """Return state of the purview""" return [rel.maximal_state(mice)[0][node] for node in mice.purview] @@ -111,7 +110,6 @@ def hovertext_relation(relation): return f"
={len(relata)}-Relation=
" + relata_info + relation_info - def vertex_sizes(min_size, max_size, elements): phis = np.array( [element.phi for element in elements] @@ -286,18 +284,63 @@ def plot_relations( ) ) # Plot edges - edges_2relations_trace = go.Scatter3d( - x=edges["x"], - y=edges["y"], - z=edges["z"], - mode="lines", - name="2-Relations", - line_width=0.5, - line_color="blue", - showlegend=True, - hoverinfo="skip", - ) - fig.add_trace(edges_2relations_trace) + # edges_2relations_trace = go.Scatter3d( + # x=edges["x"], + # y=edges["y"], + # z=edges["z"], + # mode="lines", + # name="2-Relations", + # line_width=0.5, + # line_color="blue", + # showlegend=True, + # hoverinfo="skip", + # ) + # fig.add_trace(edges_2relations_trace) + + + # Plot edges separately: + two_relations = list(filter(lambda r: len(r.relata) == 2, relations)) + + two_relations_coords = [ + list(chunk_list(list(edges["x"]),2)), + list(chunk_list(list(edges["y"]),2)), + list(chunk_list(list(edges["z"]),2)), + ] + + for n,relation in enumerate(two_relations): + if n==0: + edge_2relation_trace = go.Scatter3d( + legendgroup='2-Relations', + showlegend=True, + x=two_relations_coords[0][n], + y=two_relations_coords[1][n], + z=two_relations_coords[2][n], + mode="lines", + # name=label_relation(relation), + name='2-Relations', + line_width=0.5, + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) + else: + edge_2relation_trace = go.Scatter3d( + legendgroup='2-Relations', + showlegend=False, + x=two_relations_coords[0][n], + y=two_relations_coords[1][n], + z=two_relations_coords[2][n], + mode="lines", + # name=label_relation(relation), + name='2-Relations', + line_width=0.5, + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) + fig.add_trace(edge_2relation_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From a1aec8a6d01a84a2ada36f2b4fdb1cb5444e1829 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sat, 11 Jul 2020 23:42:27 -0500 Subject: [PATCH 19/27] Renamed `vertex_sizes()` Renamed vertex_sizes() function to normalize_sizes() since applicable to edges and triangles too. --- pyphi/visualize.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index d4f701cf2..6c20ee70e 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -110,7 +110,7 @@ def hovertext_relation(relation): return f"
={len(relata)}-Relation=
" + relata_info + relation_info -def vertex_sizes(min_size, max_size, elements): +def normalize_sizes(min_size, max_size, elements): phis = np.array( [element.phi for element in elements] ) @@ -208,7 +208,7 @@ def plot_relations( fig.add_trace(labels_mechanisms_trace) # Compute purview and mechanism marker sizes - purview_sizes = vertex_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) + purview_sizes = normalize_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) mechanism_sizes = [min(phis) for phis in chunk_list(purview_sizes, 2)] # Make mechanisms trace From 29c7f33d64881bccf1610a3be729ced1d486d659 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sun, 12 Jul 2020 00:07:38 -0500 Subject: [PATCH 20/27] Update visualize.py Rounded phis to 4 decimals, added 2-relation phis as edge width normalized based on corresponding kwarg, adjusted default args. --- pyphi/visualize.py | 51 ++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 6c20ee70e..d9c0f8b2e 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -87,25 +87,25 @@ def label_relation(relation): relata_info = '
'.join([f"{label_mechanism(mice)} / {label_purview(mice)} [{mice.direction.name}]" for n,mice in enumerate(relata)]) - relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {np.round(relation.phi,4)}
" + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {phi_round(relation.phi)}
" return relata_info + relation_info def hovertext_mechanism(distinction): - return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {distinction.cause.phi}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {distinction.effect.phi}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" + return f"Distinction: {label_mechanism(distinction.cause)}
Cause: {label_purview(distinction.cause)}
Cause φ = {phi_round(distinction.cause.phi)}
Cause state: {[rel.maximal_state(distinction.cause)[0][i] for i in distinction.cause.purview]}
Effect: {label_purview(distinction.effect)}
Effect φ = {phi_round(distinction.effect.phi)}
Effect state: {[rel.maximal_state(distinction.effect)[0][i] for i in distinction.effect.purview]}" def hovertext_purview(mice): - return f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}" + return f"Distinction: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {phi_round(mice.phi)}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}" def hovertext_relation(relation): relata = relation.relata - relata_info = ''.join([f"
Distinction {n}: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {mice.phi}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}
" for n,mice in enumerate(relata)]) + relata_info = ''.join([f"
Distinction {n}: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {phi_round(mice.phi)}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}
" for n,mice in enumerate(relata)]) - relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {np.round(relation.phi,4)}
" + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {phi_round(relation.phi)}
" return f"
={len(relata)}-Relation=
" + relata_info + relation_info @@ -119,6 +119,10 @@ def normalize_sizes(min_size, max_size, elements): return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) +def phi_round(phi): + return np.round(phi, 4) + + def chunk_list(my_list, n): """Yield successive n-sized chunks from lst.""" for i in range(0, len(my_list), n): @@ -130,11 +134,12 @@ def plot_relations( relations, max_order=3, cause_effect_offset=(0.5, 0, 0), - vertex_size_range=(10, 20), - plot_dimentions=(800, 1200), - mechanism_labels_size=10, - purview_labels_size=7.5, - mesh_opacity=0.2, + vertex_size_range=(10, 40), + edge_size_range=(1, 5), + plot_dimentions=(1000, 1400), + mechanism_labels_size=20, + purview_labels_size=15, + mesh_opacity=0.1, edge_width=1, show_mechanism_labels=True, show_purview_labels=True, @@ -144,7 +149,7 @@ def plot_relations( show_mesh=True, showgrid=False, title="", - eye_coordinates=(1.25,1.25,1.25), + eye_coordinates=(0.5,0.5,0.5), ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -192,7 +197,7 @@ def plot_relations( vertices_hovertext = list(map(hovertext_purview, separated_ces)) # Make mechanism labels - xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], z[::2] + xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], [n+(vertex_size_range[1]/10**3) for n in z[::2]] labels_mechanisms_trace = go.Scatter3d( visible=show_mechanism_labels, x=xm, @@ -234,7 +239,7 @@ def plot_relations( visible=show_purview_labels, x=x, y=y, - z=z, + z=[n+(vertex_size_range[1]/10**3) for n in z], mode="text", text=purview_labels, name="Purview Labels", @@ -283,23 +288,11 @@ def plot_relations( line_group=flatten(zip(range(len(edges) // 2), range(len(edges) // 2))), ) ) - # Plot edges - # edges_2relations_trace = go.Scatter3d( - # x=edges["x"], - # y=edges["y"], - # z=edges["z"], - # mode="lines", - # name="2-Relations", - # line_width=0.5, - # line_color="blue", - # showlegend=True, - # hoverinfo="skip", - # ) - # fig.add_trace(edges_2relations_trace) - # Plot edges separately: two_relations = list(filter(lambda r: len(r.relata) == 2, relations)) + two_relations_sizes = normalize_sizes(edge_size_range[0], edge_size_range[1], two_relations) + two_relations_coords = [ list(chunk_list(list(edges["x"]),2)), @@ -318,7 +311,7 @@ def plot_relations( mode="lines", # name=label_relation(relation), name='2-Relations', - line_width=0.5, + line_width=two_relations_sizes[n], line_color="blue", hoverinfo="text", hovertext=hovertext_relation(relation), @@ -334,7 +327,7 @@ def plot_relations( mode="lines", # name=label_relation(relation), name='2-Relations', - line_width=0.5, + line_width=two_relations_sizes[n], line_color="blue", hoverinfo="text", hovertext=hovertext_relation(relation), From 2d9a8b317caa70d6d993c69a911b9bfb9bc46f2e Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sun, 12 Jul 2020 14:02:33 -0500 Subject: [PATCH 21/27] Refined `plot_relations()` Plotting triangles as separate traces --- pyphi/visualize.py | 67 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index d9c0f8b2e..0307dae37 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -343,29 +343,56 @@ def plot_relations( for j in range(features.shape[1]) if features[:, j].sum() == 3 ] + if triangles: # Extract triangle indices i, j, k = zip(*triangles) - triangles_3relations_trace = go.Mesh3d( - visible=show_mesh, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=i, - j=j, - k=k, - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=mesh_opacity, - colorscale="viridis", - showscale=False, - name="3-Relations", - showlegend=True, - hoverinfo="skip", - ) - fig.add_trace(triangles_3relations_trace) + for n,triangle in enumerate(triangles): + if n==0: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup='3-Relations', + showlegend=True, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[n]], + j=[j[n]], + k=[k[n]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=mesh_opacity, + colorscale="viridis", + showscale=False, + name="3-Relations", + hoverinfo="skip", + ) + fig.add_trace(triangle_3relation_trace) + else: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup='3-Relations', + showlegend=False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[n]], + j=[j[n]], + k=[k[n]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=mesh_opacity, + colorscale="viridis", + showscale=False, + name="3-Relations", + hoverinfo="skip", + ) + fig.add_trace(triangle_3relation_trace) + # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 60dd58a0910b34b4c4cf615a7267585ce25a2bfa Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sun, 12 Jul 2020 14:25:10 -0500 Subject: [PATCH 22/27] Update visualize.py Added 3-Relations hover label, added hoverlabel for mechanism and purview labels, formatted with black --- pyphi/visualize.py | 187 +++++++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 81 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 0307dae37..f7b1df4f0 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -84,12 +84,17 @@ def label_state(mice): def label_relation(relation): relata = relation.relata - - relata_info = '
'.join([f"{label_mechanism(mice)} / {label_purview(mice)} [{mice.direction.name}]" for n,mice in enumerate(relata)]) - + + relata_info = "
".join( + [ + f"{label_mechanism(mice)} / {label_purview(mice)} [{mice.direction.name}]" + for n, mice in enumerate(relata) + ] + ) + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {phi_round(relation.phi)}
" - - return relata_info + relation_info + + return relata_info + relation_info def hovertext_mechanism(distinction): @@ -102,21 +107,24 @@ def hovertext_purview(mice): def hovertext_relation(relation): relata = relation.relata - - relata_info = ''.join([f"
Distinction {n}: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {phi_round(mice.phi)}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}
" for n,mice in enumerate(relata)]) - + + relata_info = "".join( + [ + f"
Distinction {n}: {label_mechanism(mice)}
Direction: {mice.direction.name}
Purview: {label_purview(mice)}
φ = {phi_round(mice.phi)}
State: {[rel.maximal_state(mice)[0][i] for i in mice.purview]}
" + for n, mice in enumerate(relata) + ] + ) + relation_info = f"
Relation purview: {make_label(relation.purview, relation.subsystem.node_labels)}
Relation φ = {phi_round(relation.phi)}
" - + return f"
={len(relata)}-Relation=
" + relata_info + relation_info def normalize_sizes(min_size, max_size, elements): - phis = np.array( - [element.phi for element in elements] - ) + phis = np.array([element.phi for element in elements]) min_phi = phis.min() max_phi = phis.max() - return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) + return min_size + (((phis - min_phi) * (max_size - min_size)) / (max_phi - min_phi)) def phi_round(phi): @@ -126,7 +134,7 @@ def phi_round(phi): def chunk_list(my_list, n): """Yield successive n-sized chunks from lst.""" for i in range(0, len(my_list), n): - yield my_list[i:i + n] + yield my_list[i : i + n] def plot_relations( @@ -136,6 +144,7 @@ def plot_relations( cause_effect_offset=(0.5, 0, 0), vertex_size_range=(10, 40), edge_size_range=(1, 5), + surface_size_range=(0.05, 0.3), plot_dimentions=(1000, 1400), mechanism_labels_size=20, purview_labels_size=15, @@ -144,12 +153,13 @@ def plot_relations( show_mechanism_labels=True, show_purview_labels=True, show_vertices_mechanisms=True, - show_vertices_purviews=True, + show_vertices_purviews=True, show_edges=True, show_mesh=True, showgrid=False, title="", - eye_coordinates=(0.5,0.5,0.5), + eye_coordinates=(0.5, 0.5, 0.5), + hovermode="closest", ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -197,7 +207,11 @@ def plot_relations( vertices_hovertext = list(map(hovertext_purview, separated_ces)) # Make mechanism labels - xm, ym, zm = [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], [n+(vertex_size_range[1]/10**3) for n in z[::2]] + xm, ym, zm = ( + [c + cause_effect_offset[0] / 2 for c in x[::2]], + y[::2], + [n + (vertex_size_range[1] / 10 ** 3) for n in z[::2]], + ) labels_mechanisms_trace = go.Scatter3d( visible=show_mechanism_labels, x=xm, @@ -208,12 +222,16 @@ def plot_relations( name="Mechanism Labels", showlegend=True, textfont=dict(size=mechanism_labels_size, color="black"), - hoverinfo="skip", + hoverinfo="text", + hovertext=mechanism_hovertext, + hoverlabel=dict(bgcolor="black", font_color="white"), ) fig.add_trace(labels_mechanisms_trace) # Compute purview and mechanism marker sizes - purview_sizes = normalize_sizes(vertex_size_range[0], vertex_size_range[1], separated_ces) + purview_sizes = normalize_sizes( + vertex_size_range[0], vertex_size_range[1], separated_ces + ) mechanism_sizes = [min(phis) for phis in chunk_list(purview_sizes, 2)] # Make mechanisms trace @@ -226,10 +244,10 @@ def plot_relations( name="Mechanisms", text=mechanism_labels, showlegend=True, - marker=dict(size=mechanism_sizes, color='black'), + marker=dict(size=mechanism_sizes, color="black"), hoverinfo="text", hovertext=mechanism_hovertext, - hoverlabel=dict(bgcolor="white"), + hoverlabel=dict(bgcolor="black", font_color="white"), ) fig.add_trace(vertices_mechanisms_trace) @@ -239,13 +257,15 @@ def plot_relations( visible=show_purview_labels, x=x, y=y, - z=[n+(vertex_size_range[1]/10**3) for n in z], + z=[n + (vertex_size_range[1] / 10 ** 3) for n in z], mode="text", text=purview_labels, name="Purview Labels", showlegend=True, textfont=dict(size=purview_labels_size, color=color), - hoverinfo="skip", + hoverinfo="text", + hovertext=vertices_hovertext, + hoverlabel=dict(bgcolor=color), ) fig.add_trace(labels_purviews_trace) @@ -288,51 +308,52 @@ def plot_relations( line_group=flatten(zip(range(len(edges) // 2), range(len(edges) // 2))), ) ) - + # Plot edges separately: two_relations = list(filter(lambda r: len(r.relata) == 2, relations)) - two_relations_sizes = normalize_sizes(edge_size_range[0], edge_size_range[1], two_relations) + two_relations_sizes = normalize_sizes( + edge_size_range[0], edge_size_range[1], two_relations + ) - two_relations_coords = [ - list(chunk_list(list(edges["x"]),2)), - list(chunk_list(list(edges["y"]),2)), - list(chunk_list(list(edges["z"]),2)), - ] - - for n,relation in enumerate(two_relations): - if n==0: + list(chunk_list(list(edges["x"]), 2)), + list(chunk_list(list(edges["y"]), 2)), + list(chunk_list(list(edges["z"]), 2)), + ] + + for n, relation in enumerate(two_relations): + if n == 0: edge_2relation_trace = go.Scatter3d( - legendgroup='2-Relations', - showlegend=True, - x=two_relations_coords[0][n], - y=two_relations_coords[1][n], - z=two_relations_coords[2][n], - mode="lines", - # name=label_relation(relation), - name='2-Relations', - line_width=two_relations_sizes[n], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), - ) + legendgroup="2-Relations", + showlegend=True, + x=two_relations_coords[0][n], + y=two_relations_coords[1][n], + z=two_relations_coords[2][n], + mode="lines", + # name=label_relation(relation), + name="2-Relations", + line_width=two_relations_sizes[n], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) else: edge_2relation_trace = go.Scatter3d( - legendgroup='2-Relations', - showlegend=False, - x=two_relations_coords[0][n], - y=two_relations_coords[1][n], - z=two_relations_coords[2][n], - mode="lines", - # name=label_relation(relation), - name='2-Relations', - line_width=two_relations_sizes[n], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), - ) + legendgroup="2-Relations", + showlegend=False, + x=two_relations_coords[0][n], + y=two_relations_coords[1][n], + z=two_relations_coords[2][n], + mode="lines", + # name=label_relation(relation), + name="2-Relations", + line_width=two_relations_sizes[n], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) fig.add_trace(edge_2relation_trace) # 3-relations @@ -345,13 +366,18 @@ def plot_relations( ] if triangles: + three_relations = list(filter(lambda r: len(r.relata) == 3, relations)) + three_relations_sizes = normalize_sizes( + surface_size_range[0], surface_size_range[1], three_relations + ) # Extract triangle indices i, j, k = zip(*triangles) - for n,triangle in enumerate(triangles): - if n==0: + for n, triangle in enumerate(triangles): + relation = three_relations[n] + if n == 0: triangle_3relation_trace = go.Mesh3d( visible=show_mesh, - legendgroup='3-Relations', + legendgroup="3-Relations", showlegend=True, # x, y, and z are the coordinates of vertices x=x, @@ -363,17 +389,18 @@ def plot_relations( k=[k[n]], # Intensity of each vertex, which will be interpolated and color-coded intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=mesh_opacity, + opacity=three_relations_sizes[n], colorscale="viridis", showscale=False, name="3-Relations", - hoverinfo="skip", + hoverinfo="text", + hovertext=hovertext_relation(relation), ) fig.add_trace(triangle_3relation_trace) else: triangle_3relation_trace = go.Mesh3d( visible=show_mesh, - legendgroup='3-Relations', + legendgroup="3-Relations", showlegend=False, # x, y, and z are the coordinates of vertices x=x, @@ -385,21 +412,21 @@ def plot_relations( k=[k[n]], # Intensity of each vertex, which will be interpolated and color-coded intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=mesh_opacity, + opacity=three_relations_sizes[n], colorscale="viridis", showscale=False, name="3-Relations", - hoverinfo="skip", + hoverinfo="text", + hovertext=hovertext_relation(relation), ) fig.add_trace(triangle_3relation_trace) - # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - axes_range = [(min(d)-1,max(d)+1) for d in (x,y,z)] + axes_range = [(min(d) - 1, max(d) + 1) for d in (x, y, z)] axes = [ - dict( + dict( showbackground=False, showline=False, zeroline=False, @@ -410,22 +437,20 @@ def plot_relations( autorange=False, range=axes_range[dimension], backgroundcolor="white", - title='', - ) + title="", + ) for dimension in range(3) - ] + ] layout = go.Layout( showlegend=True, scene_xaxis=axes[0], - scene_yaxis=axes[1], + scene_yaxis=axes[1], scene_zaxis=axes[2], scene_camera=dict( - eye=dict( - x=eye_coordinates[0], y=eye_coordinates[1], z=eye_coordinates[2] - ) + eye=dict(x=eye_coordinates[0], y=eye_coordinates[1], z=eye_coordinates[2]) ), - hovermode="closest", + hovermode=hovermode, title=title, legend=dict( title=dict( @@ -440,5 +465,5 @@ def plot_relations( # Apply layout fig.layout = layout - + return fig From 7083f741885dc0c40ff5f75844a521745cee6c6e Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Sun, 12 Jul 2020 18:35:18 -0500 Subject: [PATCH 23/27] Update visualize.py Changed n to r for relation index --- pyphi/visualize.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index f7b1df4f0..d9506b05e 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -321,18 +321,18 @@ def plot_relations( list(chunk_list(list(edges["z"]), 2)), ] - for n, relation in enumerate(two_relations): - if n == 0: + for r, relation in enumerate(two_relations): + if r == 0: edge_2relation_trace = go.Scatter3d( legendgroup="2-Relations", showlegend=True, - x=two_relations_coords[0][n], - y=two_relations_coords[1][n], - z=two_relations_coords[2][n], + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], mode="lines", # name=label_relation(relation), name="2-Relations", - line_width=two_relations_sizes[n], + line_width=two_relations_sizes[r], line_color="blue", hoverinfo="text", hovertext=hovertext_relation(relation), @@ -342,13 +342,13 @@ def plot_relations( edge_2relation_trace = go.Scatter3d( legendgroup="2-Relations", showlegend=False, - x=two_relations_coords[0][n], - y=two_relations_coords[1][n], - z=two_relations_coords[2][n], + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], mode="lines", # name=label_relation(relation), name="2-Relations", - line_width=two_relations_sizes[n], + line_width=two_relations_sizes[r], line_color="blue", hoverinfo="text", hovertext=hovertext_relation(relation), @@ -372,9 +372,9 @@ def plot_relations( ) # Extract triangle indices i, j, k = zip(*triangles) - for n, triangle in enumerate(triangles): - relation = three_relations[n] - if n == 0: + for r, triangle in enumerate(triangles): + relation = three_relations[r] + if r == 0: triangle_3relation_trace = go.Mesh3d( visible=show_mesh, legendgroup="3-Relations", @@ -384,12 +384,12 @@ def plot_relations( y=y, z=z, # i, j, and k are the vertices of triangles - i=[i[n]], - j=[j[n]], - k=[k[n]], + i=[i[r]], + j=[j[r]], + k=[k[r]], # Intensity of each vertex, which will be interpolated and color-coded intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[n], + opacity=three_relations_sizes[r], colorscale="viridis", showscale=False, name="3-Relations", @@ -407,12 +407,12 @@ def plot_relations( y=y, z=z, # i, j, and k are the vertices of triangles - i=[i[n]], - j=[j[n]], - k=[k[n]], + i=[i[r]], + j=[j[r]], + k=[k[r]], # Intensity of each vertex, which will be interpolated and color-coded intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[n], + opacity=three_relations_sizes[r], colorscale="viridis", showscale=False, name="3-Relations", From 31a66177a966cc52667a7703bdbf1feb6ea76c4f Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Wed, 15 Jul 2020 16:03:14 -0500 Subject: [PATCH 24/27] Update visualize.py Added save digraph function, added digraph plot, formatted code --- pyphi/visualize.py | 365 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 274 insertions(+), 91 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index d9506b05e..f310a9074 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -10,6 +10,11 @@ from plotly import express as px from plotly import graph_objs as go from umap import UMAP +from tqdm.notebook import tqdm + +import networkx as nx +from networkx.drawing.nx_agraph import graphviz_layout, to_agraph +from IPython.display import Image from . import relations as rel @@ -137,15 +142,53 @@ def chunk_list(my_list, n): yield my_list[i : i + n] +def format_node(n, subsystem): + node_format = { + "label": subsystem.node_labels[n], + "style": "filled" if subsystem.state[n] == 1 else "", + "fillcolor": "black" if subsystem.state[n] == 1 else "", + "fontcolor": "white" if subsystem.state[n] == 1 else "black", + } + return node_format + + +def save_digraph( + subsystem, digraph_filename="digraph.png", plot_digraph=False, layout="dot" +): + + G = nx.DiGraph() + + for n in range(subsystem.size): + node_info = format_node(n, subsystem) + G.add_node( + node_info["label"], + style=node_info["style"], + fillcolor=node_info["fillcolor"], + fontcolor=node_info["fontcolor"], + ) + + edges = [subsystem.indices2nodes(indices) for indices in np.argwhere(subsystem.cm)] + + G.add_edges_from(edges) + G.graph["node"] = {"shape": "circle"} + + A = to_agraph(G) + A.layout(layout) + A.draw(digraph_filename) + if plot_digraph: + return Image(digraph_filename) + + def plot_relations( + subsystem, ces, relations, max_order=3, - cause_effect_offset=(0.5, 0, 0), + cause_effect_offset=(0.3, 0, 0), vertex_size_range=(10, 40), edge_size_range=(1, 5), surface_size_range=(0.05, 0.3), - plot_dimentions=(1000, 1400), + plot_dimentions=(1000, 1600), mechanism_labels_size=20, purview_labels_size=15, mesh_opacity=0.1, @@ -154,12 +197,16 @@ def plot_relations( show_purview_labels=True, show_vertices_mechanisms=True, show_vertices_purviews=True, - show_edges=True, - show_mesh=True, + show_edges="legendonly", + show_mesh="legendonly", + show_node_qfolds=False, + show_mechanism_qfolds=True, showgrid=False, - title="", + network_name="", eye_coordinates=(0.5, 0.5, 0.5), - hovermode="closest", + hovermode="x", + digraph_filename="digraph.png", + digraph_layout="dot", ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -198,6 +245,10 @@ def plot_relations( # Extract vertex indices for plotly x, y, z = coords[:, 0], coords[:, 1], coords[:, 2] + # Get node labels and indices for future use: + node_labels = subsystem.node_labels + node_indices = subsystem.node_indices + # Get mechanism and purview labels mechanism_labels = list(map(label_mechanism, ces)) mechanism_labels_x2 = list(map(label_mechanism, separated_ces)) @@ -216,7 +267,7 @@ def plot_relations( visible=show_mechanism_labels, x=xm, y=ym, - z=zm, + z=[n + (vertex_size_range[1] / 10 ** 3) for n in zm], mode="text", text=mechanism_labels, name="Mechanism Labels", @@ -321,39 +372,86 @@ def plot_relations( list(chunk_list(list(edges["z"]), 2)), ] - for r, relation in enumerate(two_relations): - if r == 0: - edge_2relation_trace = go.Scatter3d( - legendgroup="2-Relations", - showlegend=True, - x=two_relations_coords[0][r], - y=two_relations_coords[1][r], - z=two_relations_coords[2][r], - mode="lines", - # name=label_relation(relation), - name="2-Relations", - line_width=two_relations_sizes[r], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), - ) - else: - edge_2relation_trace = go.Scatter3d( - legendgroup="2-Relations", - showlegend=False, - x=two_relations_coords[0][r], - y=two_relations_coords[1][r], - z=two_relations_coords[2][r], - mode="lines", - # name=label_relation(relation), - name="2-Relations", - line_width=two_relations_sizes[r], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), - ) + legend_nodes = [] + legend_mechanisms = [] + for r, relation in tqdm( + enumerate(two_relations), desc="Computing edges", total=len(two_relations) + ): + relation_nodes = list(flatten(relation.mechanisms)) + + # Make node contexts traces and legendgroups + if show_node_qfolds: + for node in node_indices: + node_label = make_label([node], node_labels) + if node in relation_nodes: + + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup=f"Node {node_label} q-fold", + showlegend=True if node not in legend_nodes else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + name=f"Node {node_label} q-fold", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(edge_2relation_trace) + + if node not in legend_nodes: + + legend_nodes.append(node) + + # Make nechanism contexts traces and legendgroups + if show_mechanism_qfolds: + mechanisms_list = [distinction.mechanism for distinction in ces] + for mechanism in mechanisms_list: + mechanism_label = make_label(mechanism, node_labels) + if mechanism in relation.mechanisms: + + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup=f"Mechanism {mechanism_label} q-fold", + showlegend=True + if mechanism_label not in legend_mechanisms + else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + name=f"Mechanism {mechanism_label} q-fold", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(edge_2relation_trace) + + if mechanism_label not in legend_mechanisms: + + legend_mechanisms.append(mechanism_label) + + # Make all 2-relations traces and legendgroup + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup="All 2-Relations", + showlegend=True if r == 0 else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + # name=label_relation(relation), + name="All 2-Relations", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) + fig.add_trace(edge_2relation_trace) # 3-relations @@ -372,56 +470,99 @@ def plot_relations( ) # Extract triangle indices i, j, k = zip(*triangles) - for r, triangle in enumerate(triangles): + for r, triangle in tqdm( + enumerate(triangles), desc="Computing triangles", total=len(triangles) + ): relation = three_relations[r] - if r == 0: - triangle_3relation_trace = go.Mesh3d( - visible=show_mesh, - legendgroup="3-Relations", - showlegend=True, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=[i[r]], - j=[j[r]], - k=[k[r]], - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[r], - colorscale="viridis", - showscale=False, - name="3-Relations", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(triangle_3relation_trace) - else: - triangle_3relation_trace = go.Mesh3d( - visible=show_mesh, - legendgroup="3-Relations", - showlegend=False, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=[i[r]], - j=[j[r]], - k=[k[r]], - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[r], - colorscale="viridis", - showscale=False, - name="3-Relations", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(triangle_3relation_trace) - - # Create figure + relation_nodes = list(flatten(relation.mechanisms)) + + if show_node_qfolds: + for node in node_indices: + node_label = make_label([node], node_labels) + if node in relation_nodes: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup=f"Node {node_label} q-fold", + showlegend=True if node not in legend_nodes else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name=f"Node {node_label} q-fold", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) + + if node not in legend_nodes: + + legend_nodes.append(node) + + if show_mechanism_qfolds: + mechanisms_list = [distinction.mechanism for distinction in ces] + for mechanism in mechanisms_list: + mechanism_label = make_label(mechanism, node_labels) + if mechanism in relation.mechanisms: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup=f"Mechanism {mechanism_label} q-fold", + showlegend=True + if mechanism_label not in legend_mechanisms + else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name=f"Mechanism {mechanism_label} q-fold", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) + if mechanism_label not in legend_mechanisms: + legend_mechanisms.append(mechanism_label) + + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup="All 3-Relations", + showlegend=True if r == 0 else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name="All 3-Relations", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) + + # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ axes_range = [(min(d) - 1, max(d) + 1) for d in (x, y, z)] @@ -451,14 +592,15 @@ def plot_relations( eye=dict(x=eye_coordinates[0], y=eye_coordinates[1], z=eye_coordinates[2]) ), hovermode=hovermode, - title=title, + title=f"{network_name} Q-STRUCTURE", + title_font_size=30, legend=dict( title=dict( text="Trace legend (click trace to show/hide):", font=dict(color="black", size=15), ) ), - autosize=True, + autosize=False, height=plot_dimentions[0], width=plot_dimentions[1], ) @@ -466,4 +608,45 @@ def plot_relations( # Apply layout fig.layout = layout + # Create system image + save_digraph(subsystem, digraph_filename, layout=digraph_layout) + digraph_coords = (-0.35, 1) + digraph_size = (0.3, 0.4) + + fig.add_layout_image( + dict( + name="Causal model", + source=digraph_filename, + # xref="paper", yref="paper", + x=digraph_coords[0], + y=digraph_coords[1], + sizex=digraph_size[0], + sizey=digraph_size[1], + xanchor="left", + yanchor="top", + ) + ) + + draft_template = go.layout.Template() + draft_template.layout.annotations = [ + dict( + name="Causal model", + text="Causal model", + opacity=1, + font=dict(color="black", size=20), + xref="paper", + yref="paper", + x=digraph_coords[0], + y=digraph_coords[1] + 0.05, + xanchor="left", + yanchor="bottom", + showarrow=False, + ) + ] + fig.update_layout( + margin=dict(l=400), + template=draft_template, + annotations=[dict(templateitemname="Causal model", visible=True)], + ) + return fig From d2c6d0569cb73071487933caee8d7625980cbca4 Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Thu, 16 Jul 2020 22:47:58 -0500 Subject: [PATCH 25/27] Update visualize.py Added option to use distinction orders as z values --- pyphi/visualize.py | 540 ++++++++++++++++++++++++--------------------- 1 file changed, 284 insertions(+), 256 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index f310a9074..b66758208 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -47,9 +47,13 @@ def feature_matrix(ces, relations): return features -def get_coords(data, y=None, **params): +def get_coords(data, y=None, n_components=3, **params): umap = UMAP( - n_components=3, metric="euclidean", n_neighbors=30, min_dist=0.5, **params, + n_components=n_components, + metric="euclidean", + n_neighbors=30, + min_dist=0.5, + **params, ) return umap.fit_transform(data, y=y) @@ -186,13 +190,11 @@ def plot_relations( max_order=3, cause_effect_offset=(0.3, 0, 0), vertex_size_range=(10, 40), - edge_size_range=(1, 5), - surface_size_range=(0.05, 0.3), + edge_size_range=(0.5, 2), + surface_size_range=(0.005, 0.1), plot_dimentions=(1000, 1600), mechanism_labels_size=20, purview_labels_size=15, - mesh_opacity=0.1, - edge_width=1, show_mechanism_labels=True, show_purview_labels=True, show_vertices_mechanisms=True, @@ -201,12 +203,15 @@ def plot_relations( show_mesh="legendonly", show_node_qfolds=False, show_mechanism_qfolds=True, - showgrid=False, + show_grid=False, network_name="", eye_coordinates=(0.5, 0.5, 0.5), hovermode="x", digraph_filename="digraph.png", digraph_layout="dot", + save_plot_to_html=True, + show_causal_model=True, + order_on_z_axis=True, ): # Select only relations <= max_order relations = list(filter(lambda r: len(r.relata) <= max_order, relations)) @@ -229,7 +234,12 @@ def plot_relations( # NOTE: This depends on the implementation of `separate_ces`; causes and # effects are assumed to be adjacent in the returned list umap_features = features[0::2] + features[1::2] - distinction_coords = get_coords(umap_features) + if order_on_z_axis: + distinction_coords = get_coords(umap_features, n_components=2) + cause_effect_offset = cause_effect_offset[:2] + + else: + distinction_coords = get_coords(umap_features) # Duplicate causes and effects so they can be plotted separately coords = np.empty( (distinction_coords.shape[0] * 2, distinction_coords.shape[1]), @@ -243,7 +253,11 @@ def plot_relations( # Purviews # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extract vertex indices for plotly - x, y, z = coords[:, 0], coords[:, 1], coords[:, 2] + x, y = coords[:, 0], coords[:, 1] + if order_on_z_axis: + z = np.array([len(c.mechanism) for c in separated_ces]) + else: + z = coords[:, 2] # Get node labels and indices for future use: node_labels = subsystem.node_labels @@ -261,7 +275,8 @@ def plot_relations( xm, ym, zm = ( [c + cause_effect_offset[0] / 2 for c in x[::2]], y[::2], - [n + (vertex_size_range[1] / 10 ** 3) for n in z[::2]], + z[::2], + # [n + (vertex_size_range[1] / 10 ** 3) for n in z[::2]], ) labels_mechanisms_trace = go.Scatter3d( visible=show_mechanism_labels, @@ -339,228 +354,236 @@ def plot_relations( ) fig.add_trace(vertices_purviews_trace) + # Initialize lists for legend + legend_nodes = [] + legend_mechanisms = [] + # 2-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Get edges from all relations - edges = list( - flatten( - relation_vertex_indices(features, j) - for j in range(features.shape[1]) - if features[:, j].sum() == 2 - ) - ) - if edges: - # Convert to DataFrame - edges = pd.DataFrame( - dict( - x=x[edges], - y=y[edges], - z=z[edges], - line_group=flatten(zip(range(len(edges) // 2), range(len(edges) // 2))), + if show_edges: + # Get edges from all relations + edges = list( + flatten( + relation_vertex_indices(features, j) + for j in range(features.shape[1]) + if features[:, j].sum() == 2 ) ) + if edges: + # Convert to DataFrame + edges = pd.DataFrame( + dict( + x=x[edges], + y=y[edges], + z=z[edges], + line_group=flatten( + zip(range(len(edges) // 2), range(len(edges) // 2)) + ), + ) + ) - # Plot edges separately: - two_relations = list(filter(lambda r: len(r.relata) == 2, relations)) - two_relations_sizes = normalize_sizes( - edge_size_range[0], edge_size_range[1], two_relations - ) - - two_relations_coords = [ - list(chunk_list(list(edges["x"]), 2)), - list(chunk_list(list(edges["y"]), 2)), - list(chunk_list(list(edges["z"]), 2)), - ] - - legend_nodes = [] - legend_mechanisms = [] - for r, relation in tqdm( - enumerate(two_relations), desc="Computing edges", total=len(two_relations) - ): - relation_nodes = list(flatten(relation.mechanisms)) - - # Make node contexts traces and legendgroups - if show_node_qfolds: - for node in node_indices: - node_label = make_label([node], node_labels) - if node in relation_nodes: - - edge_2relation_trace = go.Scatter3d( - visible=show_edges, - legendgroup=f"Node {node_label} q-fold", - showlegend=True if node not in legend_nodes else False, - x=two_relations_coords[0][r], - y=two_relations_coords[1][r], - z=two_relations_coords[2][r], - mode="lines", - name=f"Node {node_label} q-fold", - line_width=two_relations_sizes[r], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(edge_2relation_trace) - - if node not in legend_nodes: - - legend_nodes.append(node) - - # Make nechanism contexts traces and legendgroups - if show_mechanism_qfolds: - mechanisms_list = [distinction.mechanism for distinction in ces] - for mechanism in mechanisms_list: - mechanism_label = make_label(mechanism, node_labels) - if mechanism in relation.mechanisms: - - edge_2relation_trace = go.Scatter3d( - visible=show_edges, - legendgroup=f"Mechanism {mechanism_label} q-fold", - showlegend=True - if mechanism_label not in legend_mechanisms - else False, - x=two_relations_coords[0][r], - y=two_relations_coords[1][r], - z=two_relations_coords[2][r], - mode="lines", - name=f"Mechanism {mechanism_label} q-fold", - line_width=two_relations_sizes[r], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(edge_2relation_trace) - - if mechanism_label not in legend_mechanisms: - - legend_mechanisms.append(mechanism_label) - - # Make all 2-relations traces and legendgroup - edge_2relation_trace = go.Scatter3d( - visible=show_edges, - legendgroup="All 2-Relations", - showlegend=True if r == 0 else False, - x=two_relations_coords[0][r], - y=two_relations_coords[1][r], - z=two_relations_coords[2][r], - mode="lines", - # name=label_relation(relation), - name="All 2-Relations", - line_width=two_relations_sizes[r], - line_color="blue", - hoverinfo="text", - hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), + # Plot edges separately: + two_relations = list(filter(lambda r: len(r.relata) == 2, relations)) + two_relations_sizes = normalize_sizes( + edge_size_range[0], edge_size_range[1], two_relations ) - fig.add_trace(edge_2relation_trace) + two_relations_coords = [ + list(chunk_list(list(edges["x"]), 2)), + list(chunk_list(list(edges["y"]), 2)), + list(chunk_list(list(edges["z"]), 2)), + ] + + for r, relation in tqdm( + enumerate(two_relations), + desc="Computing edges", + total=len(two_relations), + ): + relation_nodes = list(flatten(relation.mechanisms)) + + # Make node contexts traces and legendgroups + if show_node_qfolds: + for node in node_indices: + node_label = make_label([node], node_labels) + if node in relation_nodes: + + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup=f"Node {node_label} q-fold", + showlegend=True if node not in legend_nodes else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + name=f"Node {node_label} q-fold", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(edge_2relation_trace) + + if node not in legend_nodes: + + legend_nodes.append(node) + + # Make nechanism contexts traces and legendgroups + if show_mechanism_qfolds: + mechanisms_list = [distinction.mechanism for distinction in ces] + for mechanism in mechanisms_list: + mechanism_label = make_label(mechanism, node_labels) + if mechanism in relation.mechanisms: + + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup=f"Mechanism {mechanism_label} q-fold", + showlegend=True + if mechanism_label not in legend_mechanisms + else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + name=f"Mechanism {mechanism_label} q-fold", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(edge_2relation_trace) + + if mechanism_label not in legend_mechanisms: + + legend_mechanisms.append(mechanism_label) + + # Make all 2-relations traces and legendgroup + edge_2relation_trace = go.Scatter3d( + visible=show_edges, + legendgroup="All 2-Relations", + showlegend=True if r == 0 else False, + x=two_relations_coords[0][r], + y=two_relations_coords[1][r], + z=two_relations_coords[2][r], + mode="lines", + # name=label_relation(relation), + name="All 2-Relations", + line_width=two_relations_sizes[r], + line_color="blue", + hoverinfo="text", + hovertext=hovertext_relation(relation), + # text=label_two_relation(relation), + ) + + fig.add_trace(edge_2relation_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Get triangles from all relations - triangles = [ - relation_vertex_indices(features, j) - for j in range(features.shape[1]) - if features[:, j].sum() == 3 - ] + if show_mesh: + triangles = [ + relation_vertex_indices(features, j) + for j in range(features.shape[1]) + if features[:, j].sum() == 3 + ] - if triangles: - three_relations = list(filter(lambda r: len(r.relata) == 3, relations)) - three_relations_sizes = normalize_sizes( - surface_size_range[0], surface_size_range[1], three_relations - ) - # Extract triangle indices - i, j, k = zip(*triangles) - for r, triangle in tqdm( - enumerate(triangles), desc="Computing triangles", total=len(triangles) - ): - relation = three_relations[r] - relation_nodes = list(flatten(relation.mechanisms)) - - if show_node_qfolds: - for node in node_indices: - node_label = make_label([node], node_labels) - if node in relation_nodes: - triangle_3relation_trace = go.Mesh3d( - visible=show_mesh, - legendgroup=f"Node {node_label} q-fold", - showlegend=True if node not in legend_nodes else False, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=[i[r]], - j=[j[r]], - k=[k[r]], - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[r], - colorscale="viridis", - showscale=False, - name=f"Node {node_label} q-fold", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(triangle_3relation_trace) - - if node not in legend_nodes: - - legend_nodes.append(node) - - if show_mechanism_qfolds: - mechanisms_list = [distinction.mechanism for distinction in ces] - for mechanism in mechanisms_list: - mechanism_label = make_label(mechanism, node_labels) - if mechanism in relation.mechanisms: - triangle_3relation_trace = go.Mesh3d( - visible=show_mesh, - legendgroup=f"Mechanism {mechanism_label} q-fold", - showlegend=True - if mechanism_label not in legend_mechanisms - else False, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=[i[r]], - j=[j[r]], - k=[k[r]], - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[r], - colorscale="viridis", - showscale=False, - name=f"Mechanism {mechanism_label} q-fold", - hoverinfo="text", - hovertext=hovertext_relation(relation), - ) - fig.add_trace(triangle_3relation_trace) - if mechanism_label not in legend_mechanisms: - legend_mechanisms.append(mechanism_label) - - triangle_3relation_trace = go.Mesh3d( - visible=show_mesh, - legendgroup="All 3-Relations", - showlegend=True if r == 0 else False, - # x, y, and z are the coordinates of vertices - x=x, - y=y, - z=z, - # i, j, and k are the vertices of triangles - i=[i[r]], - j=[j[r]], - k=[k[r]], - # Intensity of each vertex, which will be interpolated and color-coded - intensity=np.linspace(0, 1, len(x), endpoint=True), - opacity=three_relations_sizes[r], - colorscale="viridis", - showscale=False, - name="All 3-Relations", - hoverinfo="text", - hovertext=hovertext_relation(relation), + if triangles: + three_relations = list(filter(lambda r: len(r.relata) == 3, relations)) + three_relations_sizes = normalize_sizes( + surface_size_range[0], surface_size_range[1], three_relations ) - fig.add_trace(triangle_3relation_trace) + # Extract triangle indices + i, j, k = zip(*triangles) + for r, triangle in tqdm( + enumerate(triangles), desc="Computing triangles", total=len(triangles) + ): + relation = three_relations[r] + relation_nodes = list(flatten(relation.mechanisms)) + + if show_node_qfolds: + for node in node_indices: + node_label = make_label([node], node_labels) + if node in relation_nodes: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup=f"Node {node_label} q-fold", + showlegend=True if node not in legend_nodes else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name=f"Node {node_label} q-fold", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) + + if node not in legend_nodes: + + legend_nodes.append(node) + + if show_mechanism_qfolds: + mechanisms_list = [distinction.mechanism for distinction in ces] + for mechanism in mechanisms_list: + mechanism_label = make_label(mechanism, node_labels) + if mechanism in relation.mechanisms: + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup=f"Mechanism {mechanism_label} q-fold", + showlegend=True + if mechanism_label not in legend_mechanisms + else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name=f"Mechanism {mechanism_label} q-fold", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) + if mechanism_label not in legend_mechanisms: + legend_mechanisms.append(mechanism_label) + + triangle_3relation_trace = go.Mesh3d( + visible=show_mesh, + legendgroup="All 3-Relations", + showlegend=True if r == 0 else False, + # x, y, and z are the coordinates of vertices + x=x, + y=y, + z=z, + # i, j, and k are the vertices of triangles + i=[i[r]], + j=[j[r]], + k=[k[r]], + # Intensity of each vertex, which will be interpolated and color-coded + intensity=np.linspace(0, 1, len(x), endpoint=True), + opacity=three_relations_sizes[r], + colorscale="viridis", + showscale=False, + name="All 3-Relations", + hoverinfo="text", + hovertext=hovertext_relation(relation), + ) + fig.add_trace(triangle_3relation_trace) # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -571,7 +594,7 @@ def plot_relations( showbackground=False, showline=False, zeroline=False, - showgrid=showgrid, + showgrid=show_grid, gridcolor="lightgray", showticklabels=False, showspikes=True, @@ -608,45 +631,50 @@ def plot_relations( # Apply layout fig.layout = layout - # Create system image - save_digraph(subsystem, digraph_filename, layout=digraph_layout) - digraph_coords = (-0.35, 1) - digraph_size = (0.3, 0.4) + if show_causal_model: + # Create system image + # TODO check why it doesn't show if you write the img to html + save_digraph(subsystem, digraph_filename, layout=digraph_layout) + digraph_coords = (-0.35, 1) + digraph_size = (0.3, 0.4) - fig.add_layout_image( - dict( - name="Causal model", - source=digraph_filename, - # xref="paper", yref="paper", - x=digraph_coords[0], - y=digraph_coords[1], - sizex=digraph_size[0], - sizey=digraph_size[1], - xanchor="left", - yanchor="top", + fig.add_layout_image( + dict( + name="Causal model", + source=digraph_filename, + # xref="paper", yref="paper", + x=digraph_coords[0], + y=digraph_coords[1], + sizex=digraph_size[0], + sizey=digraph_size[1], + xanchor="left", + yanchor="top", + ) ) - ) - draft_template = go.layout.Template() - draft_template.layout.annotations = [ - dict( - name="Causal model", - text="Causal model", - opacity=1, - font=dict(color="black", size=20), - xref="paper", - yref="paper", - x=digraph_coords[0], - y=digraph_coords[1] + 0.05, - xanchor="left", - yanchor="bottom", - showarrow=False, + draft_template = go.layout.Template() + draft_template.layout.annotations = [ + dict( + name="Causal model", + text="Causal model", + opacity=1, + font=dict(color="black", size=20), + xref="paper", + yref="paper", + x=digraph_coords[0], + y=digraph_coords[1] + 0.05, + xanchor="left", + yanchor="bottom", + showarrow=False, + ) + ] + fig.update_layout( + margin=dict(l=400), + template=draft_template, + annotations=[dict(templateitemname="Causal model", visible=True)], ) - ] - fig.update_layout( - margin=dict(l=400), - template=draft_template, - annotations=[dict(templateitemname="Causal model", visible=True)], - ) + + if save_plot_to_html: + plotly.io.write_html(fig, f"{network_name}_CES.html") return fig From 8555f3cd859cc8c7b074cbbbf45dbc9fcb6ffffe Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Thu, 16 Jul 2020 22:52:03 -0500 Subject: [PATCH 26/27] Renamed `plot_relations()` Renamed `plot_relations()` to `plot_ces()` --- pyphi/visualize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index b66758208..79a0c38ca 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -183,7 +183,7 @@ def save_digraph( return Image(digraph_filename) -def plot_relations( +def plot_ces( subsystem, ces, relations, From 7c9d7bd91e74000cc761877c879e574d1cb6facb Mon Sep 17 00:00:00 2001 From: Matteo Grasso Date: Fri, 17 Jul 2020 00:11:47 -0500 Subject: [PATCH 27/27] Update visualize.py Added function `get_edge_color()` for two relations based on type of overlap --- pyphi/visualize.py | 55 +++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/pyphi/visualize.py b/pyphi/visualize.py index 79a0c38ca..414c79a43 100644 --- a/pyphi/visualize.py +++ b/pyphi/visualize.py @@ -183,6 +183,25 @@ def save_digraph( return Image(digraph_filename) +def get_edge_color(relation): + p0 = list(relation.relata.purviews)[0] + p1 = list(relation.relata.purviews)[1] + rp = relation.purview + # Isotext (mutual full-overlap) + if p0 == p1 == rp: + return "fuchsia" + # Sub/Supertext (inclusion / full-overlap) + elif p0 != p1 and (all(n in p1 for n in p0) or all(n in p0 for n in p1)): + return "indigo" + # Paratext (connection / partial-overlap) + elif (p0 == p1 != rp) or ( + any(n in p1 for n in p0) and not all(n in p1 for n in p0) + ): + return "cyan" + else: + raise ValueError("Unexpected relation type, check function to cover all cases") + + def plot_ces( subsystem, ces, @@ -190,13 +209,13 @@ def plot_ces( max_order=3, cause_effect_offset=(0.3, 0, 0), vertex_size_range=(10, 40), - edge_size_range=(0.5, 2), + edge_size_range=(0.5, 4), surface_size_range=(0.005, 0.1), plot_dimentions=(1000, 1600), mechanism_labels_size=20, purview_labels_size=15, show_mechanism_labels=True, - show_purview_labels=True, + show_purview_labels="legendonly", show_vertices_mechanisms=True, show_vertices_purviews=True, show_edges="legendonly", @@ -400,6 +419,7 @@ def plot_ces( total=len(two_relations), ): relation_nodes = list(flatten(relation.mechanisms)) + relation_color = get_edge_color(relation) # Make node contexts traces and legendgroups if show_node_qfolds: @@ -407,7 +427,7 @@ def plot_ces( node_label = make_label([node], node_labels) if node in relation_nodes: - edge_2relation_trace = go.Scatter3d( + edge_two_relation_trace = go.Scatter3d( visible=show_edges, legendgroup=f"Node {node_label} q-fold", showlegend=True if node not in legend_nodes else False, @@ -417,11 +437,11 @@ def plot_ces( mode="lines", name=f"Node {node_label} q-fold", line_width=two_relations_sizes[r], - line_color="blue", + line_color=relation_color, hoverinfo="text", hovertext=hovertext_relation(relation), ) - fig.add_trace(edge_2relation_trace) + fig.add_trace(edge_two_relation_trace) if node not in legend_nodes: @@ -434,7 +454,7 @@ def plot_ces( mechanism_label = make_label(mechanism, node_labels) if mechanism in relation.mechanisms: - edge_2relation_trace = go.Scatter3d( + edge_two_relation_trace = go.Scatter3d( visible=show_edges, legendgroup=f"Mechanism {mechanism_label} q-fold", showlegend=True @@ -446,18 +466,18 @@ def plot_ces( mode="lines", name=f"Mechanism {mechanism_label} q-fold", line_width=two_relations_sizes[r], - line_color="blue", + line_color=relation_color, hoverinfo="text", hovertext=hovertext_relation(relation), ) - fig.add_trace(edge_2relation_trace) + fig.add_trace(edge_two_relation_trace) if mechanism_label not in legend_mechanisms: legend_mechanisms.append(mechanism_label) # Make all 2-relations traces and legendgroup - edge_2relation_trace = go.Scatter3d( + edge_two_relation_trace = go.Scatter3d( visible=show_edges, legendgroup="All 2-Relations", showlegend=True if r == 0 else False, @@ -468,13 +488,12 @@ def plot_ces( # name=label_relation(relation), name="All 2-Relations", line_width=two_relations_sizes[r], - line_color="blue", + line_color=relation_color, hoverinfo="text", hovertext=hovertext_relation(relation), - # text=label_two_relation(relation), ) - fig.add_trace(edge_2relation_trace) + fig.add_trace(edge_two_relation_trace) # 3-relations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -503,7 +522,7 @@ def plot_ces( for node in node_indices: node_label = make_label([node], node_labels) if node in relation_nodes: - triangle_3relation_trace = go.Mesh3d( + triangle_three_relation_trace = go.Mesh3d( visible=show_mesh, legendgroup=f"Node {node_label} q-fold", showlegend=True if node not in legend_nodes else False, @@ -524,7 +543,7 @@ def plot_ces( hoverinfo="text", hovertext=hovertext_relation(relation), ) - fig.add_trace(triangle_3relation_trace) + fig.add_trace(triangle_three_relation_trace) if node not in legend_nodes: @@ -535,7 +554,7 @@ def plot_ces( for mechanism in mechanisms_list: mechanism_label = make_label(mechanism, node_labels) if mechanism in relation.mechanisms: - triangle_3relation_trace = go.Mesh3d( + triangle_three_relation_trace = go.Mesh3d( visible=show_mesh, legendgroup=f"Mechanism {mechanism_label} q-fold", showlegend=True @@ -558,11 +577,11 @@ def plot_ces( hoverinfo="text", hovertext=hovertext_relation(relation), ) - fig.add_trace(triangle_3relation_trace) + fig.add_trace(triangle_three_relation_trace) if mechanism_label not in legend_mechanisms: legend_mechanisms.append(mechanism_label) - triangle_3relation_trace = go.Mesh3d( + triangle_three_relation_trace = go.Mesh3d( visible=show_mesh, legendgroup="All 3-Relations", showlegend=True if r == 0 else False, @@ -583,7 +602,7 @@ def plot_ces( hoverinfo="text", hovertext=hovertext_relation(relation), ) - fig.add_trace(triangle_3relation_trace) + fig.add_trace(triangle_three_relation_trace) # Create figure # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~