From 891ed277b6b60b000883fadcf5fa2d290451d375 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 25 Oct 2023 09:49:58 +0200 Subject: [PATCH] Added comments, descriptions and cleaned up. --- .../ui/{ => archive}/networkx_dash_overall.py | 76 ++- .../ui/assets/networkx_style.css | 93 ++- .../ui/cytoscape_dash.py | 25 - .../ui/dashvis_networkx.py | 11 - .../ui/networkx_dash.py | 73 ++- .../ui/pages/home.py | 262 +++++---- .../utils/networkx/{ => archive}/Dev.ipynb | 145 ++--- .../{ => archive}/networkX_with_sql.ipynb | 38 +- .../networkx/{ => archive}/network_graph.html | 544 ++++++++--------- .../sql_alchemy_to_networkx.ipynb | 100 ++-- .../sql_alchemy_to_networkx_v2.ipynb | 338 ++++++----- .../utils/networkx/{ => archive}/tmp.html | 550 +++++++++--------- .../utils/networkx/network_2d.py | 175 +++--- .../utils/networkx/network_3d.py | 178 +++--- .../utils/networkx/network_base.py | 36 ++ .../utils/networkx/networkx_data.py | 209 ++++--- 16 files changed, 1602 insertions(+), 1251 deletions(-) rename src/aki_prj23_transparenzregister/ui/{ => archive}/networkx_dash_overall.py (77%) delete mode 100644 src/aki_prj23_transparenzregister/ui/cytoscape_dash.py delete mode 100644 src/aki_prj23_transparenzregister/ui/dashvis_networkx.py rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/Dev.ipynb (99%) rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/networkX_with_sql.ipynb (97%) rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/network_graph.html (99%) rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/sql_alchemy_to_networkx.ipynb (99%) rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/sql_alchemy_to_networkx_v2.ipynb (99%) rename src/aki_prj23_transparenzregister/utils/networkx/{ => archive}/tmp.html (99%) create mode 100644 src/aki_prj23_transparenzregister/utils/networkx/network_base.py diff --git a/src/aki_prj23_transparenzregister/ui/networkx_dash_overall.py b/src/aki_prj23_transparenzregister/ui/archive/networkx_dash_overall.py similarity index 77% rename from src/aki_prj23_transparenzregister/ui/networkx_dash_overall.py rename to src/aki_prj23_transparenzregister/ui/archive/networkx_dash_overall.py index b1ffbc6..f196489 100644 --- a/src/aki_prj23_transparenzregister/ui/networkx_dash_overall.py +++ b/src/aki_prj23_transparenzregister/ui/archive/networkx_dash_overall.py @@ -1,21 +1,31 @@ -import pandas as pd +"""Old Module for NetworkX Graphs.""" import networkx as nx +import pandas as pd import plotly.graph_objects as go from dash import Dash, Input, Output, dcc, html + from aki_prj23_transparenzregister.config.config_providers import JsonFileConfigProvider from aki_prj23_transparenzregister.utils.sql import connector, entities -test_company = 13 #2213 # 13 +test_company = 13 # 2213 # 13 + def find_all_company_relations() -> pd.DataFrame: + """Searches for all companies and their relation in the DB. + + Returns: + pd.DataFrame: _description_ + """ session = connector.get_session(JsonFileConfigProvider("./secrets.json")) - query_companies = session.query(entities.Company) #.all() - query_relations = session.query(entities.CompanyRelation) # .all() + query_companies = session.query(entities.Company) # .all() + query_relations = session.query(entities.CompanyRelation) # .all() companies_df: pd.DataFrame = pd.read_sql(str(query_companies), session.bind) # type: ignore companies_relations_df: pd.DataFrame = pd.read_sql(str(query_relations), session.bind) # type: ignore # print(companies_relations_df) - companies_relations_df = companies_relations_df[["relation_id","company_relation_company2_id"]] + companies_relations_df = companies_relations_df[ + ["relation_id", "company_relation_company2_id"] + ] # print(companies_relations_df) company_name = [] connected_company_name = [] @@ -23,14 +33,22 @@ def find_all_company_relations() -> pd.DataFrame: companies_relations_df = companies_relations_df.head() # print(companies_relations_df) - for _, row in companies_relations_df.iterrows(): - # print(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) - # print("TEst") - company_name.append(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) - - connected_company_name.append(companies_df.loc[companies_df["company_id"] == row["company_relation_company2_id"]]["company_name"].values[0]) + for _, row in companies_relations_df.iterrows(): + # print(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) + # print("TEst") + company_name.append( + companies_df.loc[companies_df["company_id"] == row["relation_id"]][ + "company_name" + ].values[0] + ) + + connected_company_name.append( + companies_df.loc[ + companies_df["company_id"] == row["company_relation_company2_id"] + ]["company_name"].values[0] + ) # print(connected_company_name) - + # print(company_name) companies_relations_df["company_name"] = company_name companies_relations_df["connected_company_name"] = connected_company_name @@ -38,10 +56,19 @@ def find_all_company_relations() -> pd.DataFrame: # print(companies_relations_df) return companies_relations_df + # Plotly figure def networkGraph(EGDE_VAR: None) -> go.Figure: + """Create a NetworkX Graph. + + Args: + EGDE_VAR (None): _description_ + + Returns: + go.Figure: _description_ + """ # find_all_company_relations() - + edges = [] for index, row in find_all_company_relations().iterrows(): edges.append([row["company_name"], row["connected_company_name"]]) @@ -113,12 +140,11 @@ def networkGraph(EGDE_VAR: None) -> go.Figure: "mirror": True, }, } - + print(nx.eigenvector_centrality(network_graph)) measure_vector = {} network_metrics_df = pd.DataFrame() - measure_vector = nx.eigenvector_centrality(network_graph) network_metrics_df["eigenvector"] = measure_vector.values() @@ -150,15 +176,14 @@ app = Dash(__name__) app.title = "Dash Networkx" # className="networkx_style" app.layout = html.Div( - - style={'width': '49%'}, - children = [ + style={"width": "49%"}, + children=[ html.I("Write your EDGE_VAR"), html.Br(), # dcc.Dropdown(['eigenvector', 'degree', 'betweeness', 'closeness'], 'eigenvector', id='metric-dropdown'), dcc.Input(id="EGDE_VAR", type="text", value="K", debounce=True), - dcc.Graph(id="my-graph", style={'width': '49%'}), - ] + dcc.Graph(id="my-graph", style={"width": "49%"}), + ], ) @@ -167,9 +192,18 @@ app.layout = html.Div( # Input('metric-dropdown', 'value'), [Input("EGDE_VAR", "value")], ) -def update_output(EGDE_VAR: None) -> None: +def update_output(EGDE_VAR: None) -> go.Figure: + """Just Returns the go Figure of Plotly. + + Args: + EGDE_VAR (None): _description_ + + Returns: + go.Figure: _description_ + """ return networkGraph(EGDE_VAR) if __name__ == "__main__": + """Main Method to test this page.""" app.run(debug=True) diff --git a/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css b/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css index 48a6db7..ca5d9c7 100644 --- a/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css +++ b/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css @@ -4,7 +4,8 @@ margin-left: 10px; margin-right: 20px; border: 1px solid; - border-color: blue; + border-color: var(--raisin-black); + border-radius: 20px; width: 57%; height: 100%; } @@ -15,6 +16,94 @@ margin-left: 20px; margin-right: 10px; border: 1px solid; + border-color: var(--raisin-black); + border-radius: 20px; width: 37%; height: 100%; -} \ No newline at end of file +} +.networkx_style .filter-wrapper { + float: left; + width: 100%; + +} + +.networkx_style .filter-wrapper .filter-wrapper-item { + display: inline-block; + padding: 10px; + width: 31%; + +} + +.networkx_style .filter-wrapper .filter-wrapper-item .dropdown_style { + padding-bottom: 10px; + margin-top: 1px; + padding-left: 10px; + width: 100%; + font-size: '30%' + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .header { + text-align: center; + align-items: center; + align-content: center; + vertical-align: middle; + padding: 20px; + margin: 0px; + /* margin: 5px; */ + color: var(--raisin-black); + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .filter-wrapper .filter-wrapper-item .filter-description { + padding: 5px; + padding-left: 10px; + margin: 0px; + /* margin: 5px; */ + color: var(--raisin-black); + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .switch-style { + align-self: left; + float: none; + padding-bottom: 10px; + margin-top: 1px; + padding-left: 10px; + width: 80%; + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .switch-style .jAjsxw { + align-self: left; + float: none; + display: inline; + padding: 0px; + margin: 0px; + + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .graph-style { + margin-top: 10px; + padding-bottom: 0px; + display: inline; + margin: 0px; + width: 100%; + height: 100%; + /* background-color: var(--raisin-black); */ + +} + +.networkx_style .graph-style .canvas { + padding: 0px; + margin: 0px; + width: 100% + /* background-color: var(--raisin-black); */ + +} diff --git a/src/aki_prj23_transparenzregister/ui/cytoscape_dash.py b/src/aki_prj23_transparenzregister/ui/cytoscape_dash.py deleted file mode 100644 index 0387ee4..0000000 --- a/src/aki_prj23_transparenzregister/ui/cytoscape_dash.py +++ /dev/null @@ -1,25 +0,0 @@ -import dash_cytoscape as cyto -from dash import Dash, html - -app = Dash(__name__) - -app.layout = html.Div( - [ - html.P("Dash Cytoscape:"), - cyto.Cytoscape( - id="cytoscape", - elements=[ - {"data": {"id": "ca", "label": "Canada"}}, - {"data": {"id": "on", "label": "Ontario"}}, - {"data": {"id": "qc", "label": "Quebec"}}, - {"data": {"source": "ca", "target": "on"}}, - {"data": {"source": "ca", "target": "qc"}}, - ], - layout={"name": "breadthfirst"}, - style={"width": "400px", "height": "500px"}, - ), - ] -) - -if __name__ == "__main__": - app.run_server(debug=True) diff --git a/src/aki_prj23_transparenzregister/ui/dashvis_networkx.py b/src/aki_prj23_transparenzregister/ui/dashvis_networkx.py deleted file mode 100644 index 476b214..0000000 --- a/src/aki_prj23_transparenzregister/ui/dashvis_networkx.py +++ /dev/null @@ -1,11 +0,0 @@ -# https://pypi.org/project/dashvis/ - -import dash -from dash import html -from dashvis import DashNetwork - -app = dash.Dash() -app.layout = html.Div([DashNetwork(1)]) - -if __name__ == "__main__": - app.run_server(debug=True) diff --git a/src/aki_prj23_transparenzregister/ui/networkx_dash.py b/src/aki_prj23_transparenzregister/ui/networkx_dash.py index bdddc57..9b8634a 100644 --- a/src/aki_prj23_transparenzregister/ui/networkx_dash.py +++ b/src/aki_prj23_transparenzregister/ui/networkx_dash.py @@ -1,13 +1,24 @@ -import pandas as pd +"""Old NetworkX Graph which needs to be discarded in the next commits.""" import networkx as nx +import pandas as pd import plotly.graph_objects as go -from dash import Dash, Input, Output, dcc, html, callback +from dash import dcc, html + from aki_prj23_transparenzregister.config.config_providers import JsonFileConfigProvider from aki_prj23_transparenzregister.utils.sql import connector, entities -test_company = 13 #2213 # 13 +test_company = 13 # 2213 # 13 + def find_company_relations(company_id: int) -> pd.DataFrame: + """_summary_. + + Args: + company_id (int): _description_ + + Returns: + pd.DataFrame: _description_ + """ session = connector.get_session(JsonFileConfigProvider("./secrets.json")) query_companies = session.query(entities.Company) query_relations = session.query(entities.CompanyRelation) @@ -15,24 +26,43 @@ def find_company_relations(company_id: int) -> pd.DataFrame: companies_df: pd.DataFrame = pd.read_sql(str(query_companies), session.bind) # type: ignore companies_relations_df: pd.DataFrame = pd.read_sql(str(query_relations), session.bind) # type: ignore - companies_relations_df = companies_relations_df.loc[companies_relations_df["relation_id"] == company_id,:][["relation_id","company_relation_company2_id"]] - + companies_relations_df = companies_relations_df.loc[ + companies_relations_df["relation_id"] == company_id, : + ][["relation_id", "company_relation_company2_id"]] + company_name = [] connected_company_name = [] - for _, row in companies_relations_df.iterrows(): - # print(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) - company_name.append(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) - connected_company_name.append(companies_df.loc[companies_df["company_id"] == row["company_relation_company2_id"]]["company_name"].values[0]) - + for _, row in companies_relations_df.iterrows(): + # print(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) + company_name.append( + companies_df.loc[companies_df["company_id"] == row["relation_id"]][ + "company_name" + ].values[0] + ) + connected_company_name.append( + companies_df.loc[ + companies_df["company_id"] == row["company_relation_company2_id"] + ]["company_name"].values[0] + ) + # print(company_name) companies_relations_df["company_name"] = company_name companies_relations_df["connected_company_name"] = connected_company_name # print(companies_relations_df) return companies_relations_df + # Plotly figure def networkGraph(company_id: int) -> go.Figure: + """_summary_. + + Args: + company_id (int): _description_ + + Returns: + go.Figure: _description_ + """ # df = find_company_relations(test_company) edges = [] for index, row in find_company_relations(company_id).iterrows(): @@ -109,13 +139,18 @@ def networkGraph(company_id: int) -> go.Figure: # figure return go.Figure(data=[edge_trace, node_trace], layout=layout) -def networkx_component(company_id: int): - - layout = html.Div( - [ - - dcc.Graph(id="my-graph", figure=networkGraph(company_id)), - ] - ) - return layout +def networkx_component(company_id: int) -> html.Div: + """Retruns the Layout with a Graph. + + Args: + company_id (int): _description_ + + Returns: + any: _description_ + """ + return html.Div( + [ + dcc.Graph(id="my-graph", figure=networkGraph(company_id)), + ] + ) diff --git a/src/aki_prj23_transparenzregister/ui/pages/home.py b/src/aki_prj23_transparenzregister/ui/pages/home.py index 8b07938..007a7d1 100644 --- a/src/aki_prj23_transparenzregister/ui/pages/home.py +++ b/src/aki_prj23_transparenzregister/ui/pages/home.py @@ -1,34 +1,38 @@ """Content of home page.""" import dash +import dash_daq as daq import networkx as nx import pandas as pd import plotly.graph_objects as go -from dash import Input, Output, callback, html, dcc, dash_table, ctx -import dash_daq as daq - - -from aki_prj23_transparenzregister.utils.networkx.networkx_data import ( - find_all_company_relations, - find_top_companies, - get_all_person_relations, - get_all_company_relations, - filter_relation_type, - filter_relation_with_more_than_one_connection, - create_edge_and_node_list -) -from aki_prj23_transparenzregister.utils.networkx.network_3d import ( - initialize_network, - create_3d_graph, -) +from dash import Input, Output, callback, dash_table, dcc, html from aki_prj23_transparenzregister.utils.networkx.network_2d import ( create_2d_graph, ) +from aki_prj23_transparenzregister.utils.networkx.network_3d import ( + # initialize_network, + create_3d_graph, +) +from aki_prj23_transparenzregister.utils.networkx.network_base import ( + initialize_network, +) +from aki_prj23_transparenzregister.utils.networkx.networkx_data import ( + create_edge_and_node_list, + filter_relation_type, + filter_relation_with_more_than_one_connection, + find_top_companies, + get_all_company_relations, + get_all_person_relations, +) # Get Data -person_relation = filter_relation_type(get_all_person_relations(), "HAFTENDER_GESELLSCHAFTER") -company_relation = filter_relation_with_more_than_one_connection(get_all_company_relations(), "id_company_to", "id_company_from") +person_relation = filter_relation_type( + get_all_person_relations(), "HAFTENDER_GESELLSCHAFTER" +) +company_relation = filter_relation_with_more_than_one_connection( + get_all_company_relations(), "id_company_to", "id_company_from" +) dash.register_page( __name__, @@ -50,56 +54,105 @@ def networkGraph(EGDE_VAR: None) -> go.Figure: graph, metrices = initialize_network(nodes = nodes, edges = edges) # print(graph) metric = None -network = create_3d_graph(graph, nodes, edges, metrices, metric) +network = create_3d_graph(graph, nodes, edges, metrics, metric) +# Get the possible Filter values for the Dropdowns. company_relation_type_filter = get_all_person_relations()["relation_type"].unique() -print(company_relation_type_filter) person_relation_type_filter = get_all_company_relations()["relation_type"].unique() - -df = find_top_companies() -with open("src/aki_prj23_transparenzregister/ui/assets/network_graph.html") as file: - html_content = file.read() - +top_companies_df = find_top_companies() +# with open("src/aki_prj23_transparenzregister/ui/assets/network_graph.html") as file: +# html_content = file.read() layout = html.Div( - # children=[ - # # NOTE lib dir created by NetworkX has to be placed in assets - # # html.Iframe( - # # src="assets/network_graph.html", - # # style={"height": "100vh", "width": "100vw"}, - # # allow="*", - # # ) - # ] - children = html.Div( + children=html.Div( children=[ html.Div( className="top_companytable_style", children=[ html.Title(title="Top Ten Unternehmen", style={"align": "mid"}), - dash_table.DataTable(df.to_dict('records'), [{"name": i, "id": i} for i in df.columns]) - ] + dash_table.DataTable( + top_companies_df.to_dict("records"), + [{"name": i, "id": i} for i in top_companies_df.columns], + ), + ], ), html.Div( className="networkx_style", children=[ - html.Header(title="Social Graph"), - "Company Relation Type Filter:", - dcc.Dropdown(company_relation_type_filter, company_relation_type_filter[0], id='dropdown_companyrelation_filter'), - "Person Relation Type Filter:", - dcc.Dropdown(person_relation_type_filter, person_relation_type_filter[0], id='dropdown_personrelation_filter'), - "Choose Graph Metric:", - dcc.Dropdown(['None','eigenvector', 'degree', 'betweeness', 'closeness'], 'None', id='dropdown'), - # "Text", - # dcc.Input(id="EGDE_VAR", type="text", value="K", debounce=True), - daq.BooleanSwitch(id='switch', on=False), - # html.Div(id='switch'), - # dcc.Dropdown(['eigenvector', 'degree', 'betweeness', 'closeness'], 'eigenvector', id='metric-dropdown'), - # dcc.Graph(id="my-graph"), - dcc.Graph(figure = network, id='my-graph'), - # html.Div(id='my-graph'), - ] - ) + html.H1(className="header", children=["Social Graph"]), + html.Div( + className="filter-wrapper", + children=[ + html.Div( + className="filter-wrapper-item", + children=[ + html.H5( + className="filter-description", + children=["Company Relation Type Filter:"], + ), + dcc.Dropdown( + company_relation_type_filter, + company_relation_type_filter[0], + id="dropdown_companyrelation_filter", + className="dropdown_style", + ), + ], + ), + html.Div( + className="filter-wrapper-item", + children=[ + html.H5( + className="filter-description", + children=["Person Relation Type Filter:"], + ), + dcc.Dropdown( + person_relation_type_filter, + person_relation_type_filter[0], + id="dropdown_personrelation_filter", + className="dropdown_style", + ), + ], + ), + html.Div( + className="filter-wrapper-item", + children=[ + html.H5( + className="filter-description", + children=["Choose Graph Metric:"], + ), + dcc.Dropdown( + [ + "None", + "eigenvector", + "degree", + "betweeness", + "closeness", + ], + "None", + id="dropdown", + className="dropdown_style", + ), + ], + ), + ], + ), + html.Div( + className="filter-wrapper-item", + children=[ + html.H5( + className="filter-description", + children=["Switch to 2D Diagramm"], + ), + html.Div( + className="switch-style", + children=[daq.BooleanSwitch(id="switch", on=False)], + ), + ], + ), + dcc.Graph(figure=network, id="my-graph", className="graph-style"), + ], + ), ] ) ) @@ -107,78 +160,65 @@ layout = html.Div( @callback( Output("my-graph", "figure"), - # Input('metric-dropdown', 'value'), - [Input("dropdown", "value"), - Input("switch", "on"), - Input("dropdown_companyrelation_filter", "value"), - Input("dropdown_personrelation_filter", "value")], + [ + Input("dropdown", "value"), + Input("switch", "on"), + Input("dropdown_companyrelation_filter", "value"), + Input("dropdown_personrelation_filter", "value"), + ], prevent_initial_call=True, - allow_duplicate=True + allow_duplicate=True, ) -def update_figure(selected_value, on, c_relation_filter, p_relation_filter): - triggered_id = ctx.triggered_id - +def update_figure( + selected_metric: str, + switch_value: bool, + c_relation_filter_value: str, + p_relation_filter_value: str, +) -> go.Figure: + """In this Callback the Value of the Dropdown is used to filter the Data. In Addition it takes the filter for the Graph metrics and creates a new graph, or switches between 3D and 2D. - find_top_companies() + Args: + selected_metric (_type_): _description_ + switch_value (bool): _description_ + c_relation_filter_value (_type_): _description_ + p_relation_filter_value (_type_): _description_ + + Returns: + Network Graph(Plotly Figure): Plotly Figure in 3 or 2D + """ + _ = c_relation_filter_value, p_relation_filter_value + + # find_top_companies() + + metric = None if selected_metric == "None" else selected_metric - if selected_value == "None": - metric = None - else: - metric = selected_value - - - - if triggered_id == 'switch': - - if on: - return update_mode(on, selected_value) - else: - return create_3d_graph(graph, nodes, edges, metrices, metric) - elif triggered_id == 'dropdown': - - if on: - return update_mode(on, selected_value) - else: - return create_3d_graph(graph, nodes, edges, metrices, metric) - - # print(c_relation_filter) - # print(p_relation_filter) # if triggered_id == 'dropdown_companyrelation_filter' or triggered_id == 'dropdown_personrelation_filter': - # print("Hallo") # print(selected_value) - # graph, metrices = update_graph_data(person_relation_type= p_relation_filter, company_relation_type= c_relation_filter) - # if on: - # return update_mode(on, selected_value) - # else: - # return create_3d_graph(graph, nodes, edges, metrices, metric) - # print(metrices) - # print(graph) + # print(metrics) + # print(graph) + # graph, metrics = update_graph_data(person_relation_type= p_relation_filter, company_relation_type= c_relation_filter) -def update_mode(value, metric): - - if metric == "None": - metric = None - if value == True: - return create_2d_graph(graph, nodes, edges, metrices, metric) - + if switch_value: + return create_2d_graph(graph, nodes, edges, metrics, metric) + else: + return create_3d_graph(graph, nodes, edges, metrics, metric) - -def update_graph_data(person_relation_type = "HAFTENDER_GESELLSCHAFTER", company_relation_type = "GESCHAEFTSFUEHRER"): +def update_graph_data( + person_relation_type: str = "HAFTENDER_GESELLSCHAFTER", + company_relation_type: str = "GESCHAEFTSFUEHRER", +) -> tuple[nx.Graph, pd.DataFrame]: # Get Data person_df = get_all_person_relations() company_df = get_all_company_relations() person_relation = filter_relation_type(person_df, person_relation_type) company_relation = filter_relation_type(company_df, company_relation_type) - print(company_relation) # company_relation = filter_relation_with_more_than_one_connection(company_relation, "id_company_to", "id_company_from") - # print(company_relation) - #Create Edge and Node List from data - nodes, edges = create_edge_and_node_list(person_relation, company_relation) - # print(edges) - graph, metrices = initialize_network(nodes = nodes, edges = edges) - return graph, metrices - \ No newline at end of file + # Create Edge and Node List from data + nodes, edges = create_edge_and_node_list(person_relation, company_relation) + + graph, metrics = initialize_network(nodes=nodes, edges=edges) + return graph, metrics diff --git a/src/aki_prj23_transparenzregister/utils/networkx/Dev.ipynb b/src/aki_prj23_transparenzregister/utils/networkx/archive/Dev.ipynb similarity index 99% rename from src/aki_prj23_transparenzregister/utils/networkx/Dev.ipynb rename to src/aki_prj23_transparenzregister/utils/networkx/archive/Dev.ipynb index 1c0c38e..458a3c3 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/Dev.ipynb +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/Dev.ipynb @@ -1795,7 +1795,7 @@ "import networkx as nx\n", "\n", "G = graph\n", - "pos=nx.fruchterman_reingold_layout(G)\n", + "pos = nx.fruchterman_reingold_layout(G)\n", "pos" ] }, @@ -1929,7 +1929,7 @@ ], "source": [ "nodes = pd.DataFrame(pos)\n", - "nodes\n" + "nodes" ] }, { @@ -1938,41 +1938,45 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "Xv=[pos[k][0] for k in range(N)]\n", - "Yv=[pos[k][1] for k in range(N)]\n", - "Xed=[]\n", - "Yed=[]\n", + "Xv = [pos[k][0] for k in range(N)]\n", + "Yv = [pos[k][1] for k in range(N)]\n", + "Xed = []\n", + "Yed = []\n", "for edge in E:\n", - " Xed+=[pos[edge[0]][0],pos[edge[1]][0], None]\n", - " Yed+=[pos[edge[0]][1],pos[edge[1]][1], None]\n", + " Xed += [pos[edge[0]][0], pos[edge[1]][0], None]\n", + " Yed += [pos[edge[0]][1], pos[edge[1]][1], None]\n", "\n", - "trace3=Scatter(x=Xed,\n", - " y=Yed,\n", - " mode='lines',\n", - " line=dict(color='rgb(210,210,210)', width=1),\n", - " hoverinfo='none'\n", - " )\n", - "trace4=Scatter(x=Xv,\n", - " y=Yv,\n", - " mode='markers',\n", - " name='net',\n", - " marker=dict(symbol='circle-dot',\n", - " size=5,\n", - " color='#6959CD',\n", - " line=dict(color='rgb(50,50,50)', width=0.5)\n", - " ),\n", - " text=labels,\n", - " hoverinfo='text'\n", - " )\n", + "trace3 = Scatter(\n", + " x=Xed,\n", + " y=Yed,\n", + " mode=\"lines\",\n", + " line=dict(color=\"rgb(210,210,210)\", width=1),\n", + " hoverinfo=\"none\",\n", + ")\n", + "trace4 = Scatter(\n", + " x=Xv,\n", + " y=Yv,\n", + " mode=\"markers\",\n", + " name=\"net\",\n", + " marker=dict(\n", + " symbol=\"circle-dot\",\n", + " size=5,\n", + " color=\"#6959CD\",\n", + " line=dict(color=\"rgb(50,50,50)\", width=0.5),\n", + " ),\n", + " text=labels,\n", + " hoverinfo=\"text\",\n", + ")\n", "\n", - "annot=\"This networkx.Graph has the Fruchterman-Reingold layout
Code:\"+\\\n", - "\" [2]\"\n", + "annot = (\n", + " \"This networkx.Graph has the Fruchterman-Reingold layout
Code:\"\n", + " + \" [2]\"\n", + ")\n", "\n", - "data1=[trace3, trace4]\n", - "fig1=Figure(data=data1, layout=layout)\n", - "fig1['layout']['annotations'][0]['text']=annot\n", - "py.iplot(fig1, filename='Coautorship-network-nx')" + "data1 = [trace3, trace4]\n", + "fig1 = Figure(data=data1, layout=layout)\n", + "fig1[\"layout\"][\"annotations\"][0][\"text\"] = annot\n", + "py.iplot(fig1, filename=\"Coautorship-network-nx\")" ] }, { @@ -1998,12 +2002,12 @@ "import networkx as nx\n", "\n", "G = graph\n", - "pos=nx.fruchterman_reingold_layout(G)\n", + "pos = nx.fruchterman_reingold_layout(G)\n", "edge_x = []\n", "edge_y = []\n", "for edge in G.edges():\n", - " x0, y0 = G.nodes[edge[0]]['pos']\n", - " x1, y1 = G.nodes[edge[1]]['pos']\n", + " x0, y0 = G.nodes[edge[0]][\"pos\"]\n", + " x1, y1 = G.nodes[edge[1]][\"pos\"]\n", " edge_x.append(x0)\n", " edge_x.append(x1)\n", " edge_x.append(None)\n", @@ -2012,39 +2016,41 @@ " edge_y.append(None)\n", "\n", "edge_trace = go.Scatter(\n", - " x=edge_x, y=edge_y,\n", - " line=dict(width=0.5, color='#888'),\n", - " hoverinfo='none',\n", - " mode='lines')\n", + " x=edge_x,\n", + " y=edge_y,\n", + " line=dict(width=0.5, color=\"#888\"),\n", + " hoverinfo=\"none\",\n", + " mode=\"lines\",\n", + ")\n", "\n", "node_x = []\n", "node_y = []\n", "for node in G.nodes():\n", - " x, y = G.nodes[node]['pos']\n", + " x, y = G.nodes[node][\"pos\"]\n", " node_x.append(x)\n", " node_y.append(y)\n", "\n", "node_trace = go.Scatter(\n", - " x=node_x, y=node_y,\n", - " mode='markers',\n", - " hoverinfo='text',\n", + " x=node_x,\n", + " y=node_y,\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", " marker=dict(\n", " showscale=True,\n", " # colorscale options\n", " #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |\n", " #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |\n", " #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |\n", - " colorscale='YlGnBu',\n", + " colorscale=\"YlGnBu\",\n", " reversescale=True,\n", " color=[],\n", " size=10,\n", " colorbar=dict(\n", - " thickness=15,\n", - " title='Node Connections',\n", - " xanchor='left',\n", - " titleside='right'\n", + " thickness=15, title=\"Node Connections\", xanchor=\"left\", titleside=\"right\"\n", " ),\n", - " line_width=2))" + " line_width=2,\n", + " ),\n", + ")" ] }, { @@ -2057,7 +2063,7 @@ "node_text = []\n", "for node, adjacencies in enumerate(G.adjacency()):\n", " node_adjacencies.append(len(adjacencies[1]))\n", - " node_text.append('# of connections: '+str(len(adjacencies[1])))\n", + " node_text.append(\"# of connections: \" + str(len(adjacencies[1])))\n", "\n", "node_trace.marker.color = node_adjacencies\n", "node_trace.text = node_text" @@ -2069,21 +2075,28 @@ "metadata": {}, "outputs": [], "source": [ - "fig = go.Figure(data=[edge_trace, node_trace],\n", - " layout=go.Layout(\n", - " title='
Network graph made with Python',\n", - " titlefont_size=16,\n", - " showlegend=False,\n", - " hovermode='closest',\n", - " margin=dict(b=20,l=5,r=5,t=40),\n", - " annotations=[ dict(\n", - " text=\"Python code: https://plotly.com/ipython-notebooks/network-graphs/\",\n", - " showarrow=False,\n", - " xref=\"paper\", yref=\"paper\",\n", - " x=0.005, y=-0.002 ) ],\n", - " xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", - " yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))\n", - " )\n", + "fig = go.Figure(\n", + " data=[edge_trace, node_trace],\n", + " layout=go.Layout(\n", + " title=\"
Network graph made with Python\",\n", + " titlefont_size=16,\n", + " showlegend=False,\n", + " hovermode=\"closest\",\n", + " margin=dict(b=20, l=5, r=5, t=40),\n", + " annotations=[\n", + " dict(\n", + " text=\"Python code: https://plotly.com/ipython-notebooks/network-graphs/\",\n", + " showarrow=False,\n", + " xref=\"paper\",\n", + " yref=\"paper\",\n", + " x=0.005,\n", + " y=-0.002,\n", + " )\n", + " ],\n", + " xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", + " yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", + " ),\n", + ")\n", "fig.show()" ] } diff --git a/src/aki_prj23_transparenzregister/utils/networkx/networkX_with_sql.ipynb b/src/aki_prj23_transparenzregister/utils/networkx/archive/networkX_with_sql.ipynb similarity index 97% rename from src/aki_prj23_transparenzregister/utils/networkx/networkX_with_sql.ipynb rename to src/aki_prj23_transparenzregister/utils/networkx/archive/networkX_with_sql.ipynb index eb26044..4a83d78 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/networkX_with_sql.ipynb +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/networkX_with_sql.ipynb @@ -780,7 +780,9 @@ "source": [ "relations_df = pd.DataFrame(relations_query.all())\n", "relations_df[\"person_name\"] = relations_df[\"lastname\"] + relations_df[\"firstname\"]\n", - "relations_df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)\n", + "relations_df.rename(\n", + " columns={\"oldName1\": \"newName1\", \"oldName2\": \"newName2\"}, inplace=True\n", + ")\n", "relations_df" ] }, @@ -791,22 +793,21 @@ "outputs": [], "source": [ "node_template = {\n", - " \"id\": \"(company|person)_\\d\",\n", - " \"label\": \"Name from entries\",\n", - " \"type\": \"Company|Person\",\n", - " \"shape\": \"dot\",\n", - " \"color\": \"#729b79ff\",\n", - " # TODO add title for hover effect in graph \"title\": \"\"\n", - " }\n", + " \"id\": \"(company|person)_\\d\",\n", + " \"label\": \"Name from entries\",\n", + " \"type\": \"Company|Person\",\n", + " \"shape\": \"dot\",\n", + " \"color\": \"#729b79ff\",\n", + " # TODO add title for hover effect in graph \"title\": \"\"\n", + "}\n", "nodes = relations_df\n", "for index in relations_df.index:\n", - " \n", " nodes[\"index\"] = {\n", - " \"label\": company_2.name,\n", - " \"type\": \"Company\",\n", - " \"shape\": \"dot\",\n", - " \"color\": \"#729b79ff\",\n", - " }" + " \"label\": company_2.name,\n", + " \"type\": \"Company\",\n", + " \"shape\": \"dot\",\n", + " \"color\": \"#729b79ff\",\n", + " }" ] }, { @@ -879,15 +880,10 @@ " else:\n", " size = measure_vector[node_id] * 50\n", " next(\n", - " (\n", - " node.update({\"size\": size})\n", - " for node in net.nodes\n", - " if node[\"id\"] == node_id\n", - " ),\n", + " (node.update({\"size\": size}) for node in net.nodes if node[\"id\"] == node_id),\n", " None,\n", " )\n", "\n", - " \n", "\n", "net.repulsion()\n", "net.show_buttons(filter_=[\"physics\"])\n", @@ -895,7 +891,7 @@ "# net.show_buttons()\n", "\n", "# save graph as HTML\n", - "net.save_graph(\"./tmp.html\")\n" + "net.save_graph(\"./tmp.html\")" ] } ], diff --git a/src/aki_prj23_transparenzregister/utils/networkx/network_graph.html b/src/aki_prj23_transparenzregister/utils/networkx/archive/network_graph.html similarity index 99% rename from src/aki_prj23_transparenzregister/utils/networkx/network_graph.html rename to src/aki_prj23_transparenzregister/utils/networkx/archive/network_graph.html index d8a61cf..370071a 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/network_graph.html +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/network_graph.html @@ -1,272 +1,272 @@ - - - - - - - - - -
-

-
- - - - - - -
-

-
- - - - - -
- - -
-
- - -
-
-
0%
-
-
-
-
-
- - -
- - - - - + + + + + + + + + +
+

+
+ + + + + + +
+

+
+ + + + + +
+ + +
+
+ + +
+
+
0%
+
+
+
+
+
+ + +
+ + + + + diff --git a/src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx.ipynb b/src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx.ipynb similarity index 99% rename from src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx.ipynb rename to src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx.ipynb index 3c25c7b..bf0a4e1 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx.ipynb +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx.ipynb @@ -680,8 +680,10 @@ } ], "source": [ - "person_relations['id_company'] = person_relations['id_company'].apply(lambda x: f\"c_{x}\")\n", - "person_relations['id_person'] = person_relations['id_person'].apply(lambda x: f\"p_{x}\")\n", + "person_relations[\"id_company\"] = person_relations[\"id_company\"].apply(\n", + " lambda x: f\"c_{x}\"\n", + ")\n", + "person_relations[\"id_person\"] = person_relations[\"id_person\"].apply(lambda x: f\"p_{x}\")\n", "person_relations.head()" ] }, @@ -10172,7 +10174,9 @@ } ], "source": [ - "person_relations_df[[\"from_x\", \"from_y\"]] = (company_df.set_index(\"id\", drop=True)).loc[person_relations_df[\"company_id\"], [\"x\", \"y\"]]\n", + "person_relations_df[[\"from_x\", \"from_y\"]] = (company_df.set_index(\"id\", drop=True)).loc[\n", + " person_relations_df[\"company_id\"], [\"x\", \"y\"]\n", + "]\n", "person_relations_df.head().T" ] }, @@ -10202,7 +10206,9 @@ "outputs": [], "source": [ "df_temp_df: pd.DataFrame = company_df.set_index(\"id\", drop=True)\n", - "person_relations_df[[\"company_from_x\", \"company_from_y\"]] = df_temp_df.loc[person_relations_df[\"company_id\"] , [\"x\", \"y\"]].reset_index(drop=True)" + "person_relations_df[[\"company_from_x\", \"company_from_y\"]] = df_temp_df.loc[\n", + " person_relations_df[\"company_id\"], [\"x\", \"y\"]\n", + "].reset_index(drop=True)" ] }, { @@ -10213,7 +10219,9 @@ "outputs": [], "source": [ "df_person_tmp: pd.DataFrame = person_df.set_index(\"id\", drop=True)\n", - "person_relations_df[[\"to_person_x\", \"to_person_y\"]] = df_person_tmp.loc[person_relations_df[\"person_id\"] , [\"x\", \"y\"]].reset_index(drop=True)\n" + "person_relations_df[[\"to_person_x\", \"to_person_y\"]] = df_person_tmp.loc[\n", + " person_relations_df[\"person_id\"], [\"x\", \"y\"]\n", + "].reset_index(drop=True)" ] }, { @@ -10242,10 +10250,14 @@ "outputs": [], "source": [ "df_temp_df: pd.DataFrame = company_df.set_index(\"id\", drop=True)\n", - "company_relations_df[[\"company_from_x\", \"company_from_y\"]] = df_temp_df.loc[company_relations_df[\"company_from_id\"] , [\"x\", \"y\"]].reset_index(drop=True)\n", + "company_relations_df[[\"company_from_x\", \"company_from_y\"]] = df_temp_df.loc[\n", + " company_relations_df[\"company_from_id\"], [\"x\", \"y\"]\n", + "].reset_index(drop=True)\n", "\n", "\n", - "company_relations_df[[\"company_to_x\", \"company_to_y\"]] = df_temp_df.loc[company_relations_df[\"company_to_id\"] , [\"x\", \"y\"]].reset_index(drop=True)\n", + "company_relations_df[[\"company_to_x\", \"company_to_y\"]] = df_temp_df.loc[\n", + " company_relations_df[\"company_to_id\"], [\"x\", \"y\"]\n", + "].reset_index(drop=True)\n", "company_relations_df" ] }, @@ -10278,39 +10290,45 @@ "fig = go.Figure()\n", "\n", "# Scatter plot for df1\n", - "fig.add_trace(go.Scatter(\n", - " x=df1['x'],\n", - " y=df1['y'],\n", - " mode='markers',\n", - " name='DataFrame 1',\n", - " hovertext=df1[\"name\"]\n", - "))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=df1[\"x\"],\n", + " y=df1[\"y\"],\n", + " mode=\"markers\",\n", + " name=\"DataFrame 1\",\n", + " hovertext=df1[\"name\"],\n", + " )\n", + ")\n", "\n", "# Scatter plot for df2\n", - "fig.add_trace(go.Scatter(\n", - " x=df2['x'],\n", - " y=df2['y'],\n", - " mode='markers',\n", - " name='DataFrame 2',\n", - " hovertext=df2[\"firstname\"]\n", - "))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=df2[\"x\"],\n", + " y=df2[\"y\"],\n", + " mode=\"markers\",\n", + " name=\"DataFrame 2\",\n", + " hovertext=df2[\"firstname\"],\n", + " )\n", + ")\n", "\n", "# Scatter plot for df3\n", "for i in range(len(df1)):\n", - " fig.add_trace(go.Scatter(\n", - " x=[df3['company_from_x'][i], df3['to_person_x'][i]],\n", - " y=[df3['company_from_y'][i], df3['to_person_y'][i]],\n", - " mode='lines',\n", - " name='Line DataFrame 1',\n", - " line=dict(color='blue')\n", - " ))\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=[df3[\"company_from_x\"][i], df3[\"to_person_x\"][i]],\n", + " y=[df3[\"company_from_y\"][i], df3[\"to_person_y\"][i]],\n", + " mode=\"lines\",\n", + " name=\"Line DataFrame 1\",\n", + " line=dict(color=\"blue\"),\n", + " )\n", + " )\n", "\n", "# Customize the layout of the plot\n", "fig.update_layout(\n", - " title='Overlayed Scatter Plot',\n", - " xaxis=dict(title='X-axis Label'),\n", - " yaxis=dict(title='Y-axis Label'),\n", - " showlegend=True # Show legend with dataframe names\n", + " title=\"Overlayed Scatter Plot\",\n", + " xaxis=dict(title=\"X-axis Label\"),\n", + " yaxis=dict(title=\"Y-axis Label\"),\n", + " showlegend=True, # Show legend with dataframe names\n", ")\n", "\n", "# Show the plot\n", @@ -10324,13 +10342,15 @@ "outputs": [], "source": [ "for i in range(len(df1)):\n", - " fig.add_trace(go.Scatter(\n", - " x=[df1['x0_column'][i], df1['x1_column'][i]],\n", - " y=[df1['y0_column'][i], df1['y1_column'][i]],\n", - " mode='lines',\n", - " name='Line DataFrame 1',\n", - " line=dict(color='blue')\n", - " ))" + " fig.add_trace(\n", + " go.Scatter(\n", + " x=[df1[\"x0_column\"][i], df1[\"x1_column\"][i]],\n", + " y=[df1[\"y0_column\"][i], df1[\"y1_column\"][i]],\n", + " mode=\"lines\",\n", + " name=\"Line DataFrame 1\",\n", + " line=dict(color=\"blue\"),\n", + " )\n", + " )" ] }, { @@ -129718,7 +129738,7 @@ ")\n", "\n", "# Show the plot\n", - "fig.show()\n" + "fig.show()" ] }, { diff --git a/src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx_v2.ipynb b/src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx_v2.ipynb similarity index 99% rename from src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx_v2.ipynb rename to src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx_v2.ipynb index 3ba69c8..35d858d 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/sql_alchemy_to_networkx_v2.ipynb +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/sql_alchemy_to_networkx_v2.ipynb @@ -48,7 +48,7 @@ "\n", "if not os.path.exists(\"src\"):\n", " %cd \"../\"\n", - "os.path.abspath(\".\") " + "os.path.abspath(\".\")" ] }, { @@ -675,8 +675,12 @@ } ], "source": [ - "company_relations['id_company_from'] = company_relations['id_company_from'].apply(lambda x: f\"c_{x}\")\n", - "company_relations['id_company_to'] = company_relations['id_company_to'].apply(lambda x: f\"c_{x}\")\n", + "company_relations[\"id_company_from\"] = company_relations[\"id_company_from\"].apply(\n", + " lambda x: f\"c_{x}\"\n", + ")\n", + "company_relations[\"id_company_to\"] = company_relations[\"id_company_to\"].apply(\n", + " lambda x: f\"c_{x}\"\n", + ")\n", "company_relations.head()" ] }, @@ -793,8 +797,10 @@ } ], "source": [ - "person_relations['id_company'] = person_relations['id_company'].apply(lambda x: f\"c_{x}\")\n", - "person_relations['id_person'] = person_relations['id_person'].apply(lambda x: f\"p_{x}\")\n", + "person_relations[\"id_company\"] = person_relations[\"id_company\"].apply(\n", + " lambda x: f\"c_{x}\"\n", + ")\n", + "person_relations[\"id_person\"] = person_relations[\"id_person\"].apply(lambda x: f\"p_{x}\")\n", "person_relations.head()" ] }, @@ -1051,10 +1057,12 @@ "source": [ "import pandas as pd\n", "\n", + "\n", "def filter_relation_type(df: pd.DataFrame, selected_relation_type):\n", " df = df.loc[df[\"relation_type\"] == selected_relation_type]\n", " return df\n", "\n", + "\n", "relation_type_set = set(company_relations[\"relation_type\"].unique())\n", "relation_type_set\n", "# {'HAFTENDER_GESELLSCHAFTER', 'INHABER', 'KOMMANDITIST', 'LIQUIDATOR'}\n", @@ -1247,9 +1255,11 @@ } ], "source": [ - "def filter_relation_with_more_than_one_connection(df: pd.DataFrame, id_column_name_to, id_column_name_from):\n", + "def filter_relation_with_more_than_one_connection(\n", + " df: pd.DataFrame, id_column_name_to, id_column_name_from\n", + "):\n", " # print(df.columns.values)\n", - " tmp_df = pd.DataFrame(columns= df.columns.values)\n", + " tmp_df = pd.DataFrame(columns=df.columns.values)\n", " # print(tmp_df)\n", " for _index, row in df.iterrows():\n", " count = 0\n", @@ -1261,7 +1271,7 @@ " count = count + 1\n", " if count > 1:\n", " break\n", - " \n", + "\n", " if count > 1:\n", " # tmp_df = pd.concat([tmp_df, pd.DataFrame(row)])+\n", " tmp_df.loc[len(tmp_df)] = row\n", @@ -1274,7 +1284,10 @@ " count = 0\n", " return tmp_df\n", "\n", - "tmp_df = filter_relation_with_more_than_one_connection(company_relations, \"id_company_to\", \"id_company_from\")\n", + "\n", + "tmp_df = filter_relation_with_more_than_one_connection(\n", + " company_relations, \"id_company_to\", \"id_company_from\"\n", + ")\n", "tmp_df\n", "# Für Companys 10 sekunden\n", "# tmp_df = filter_relation_with_more_than_one_connection(person_relations, \"id_company\", \"id_person\")\n", @@ -1412,43 +1425,57 @@ "metadata": {}, "outputs": [], "source": [ - "def create_edge_and_node_list(person_relations: pd.DataFrame, company_relations:pd.DataFrame):\n", + "def create_edge_and_node_list(\n", + " person_relations: pd.DataFrame, company_relations: pd.DataFrame\n", + "):\n", " nodes = {}\n", " edges = []\n", "\n", " # Iterate over person relations\n", " for _index, row in person_relations.iterrows():\n", - " if node:= nodes.get(row['id_company']) is None:\n", - " nodes[row['id_company']] = {\n", - " \"id\": row['id_company'],\n", - " 'name': row['name_company'],\n", - " 'color': COLOR_COMPANY\n", + " if node := nodes.get(row[\"id_company\"]) is None:\n", + " nodes[row[\"id_company\"]] = {\n", + " \"id\": row[\"id_company\"],\n", + " \"name\": row[\"name_company\"],\n", + " \"color\": COLOR_COMPANY,\n", " }\n", - " if node:= nodes.get(row['id_person']) is None:\n", - " nodes[row['id_person']] = {\n", - " \"id\": row['id_person'],\n", - " 'firstname': row['firstname'],\n", - " 'lastname': row['lastname'],\n", - " 'date_of_birth': row['date_of_birth'],\n", - " 'color': COLOR_PERSON\n", - " } \n", - " edges.append({'from': row['id_person'], 'to': row['id_company'], 'type': row['relation_type']})\n", + " if node := nodes.get(row[\"id_person\"]) is None:\n", + " nodes[row[\"id_person\"]] = {\n", + " \"id\": row[\"id_person\"],\n", + " \"firstname\": row[\"firstname\"],\n", + " \"lastname\": row[\"lastname\"],\n", + " \"date_of_birth\": row[\"date_of_birth\"],\n", + " \"color\": COLOR_PERSON,\n", + " }\n", + " edges.append(\n", + " {\n", + " \"from\": row[\"id_person\"],\n", + " \"to\": row[\"id_company\"],\n", + " \"type\": row[\"relation_type\"],\n", + " }\n", + " )\n", "\n", " for _index, row in company_relations.iterrows():\n", - " if node:= nodes.get(row['id_company_from']) is None:\n", - " nodes[row['id_company_from']] = {\n", - " \"id\": row['id_company_from'],\n", - " 'name': row['name_company_from'],\n", - " 'color': COLOR_COMPANY\n", + " if node := nodes.get(row[\"id_company_from\"]) is None:\n", + " nodes[row[\"id_company_from\"]] = {\n", + " \"id\": row[\"id_company_from\"],\n", + " \"name\": row[\"name_company_from\"],\n", + " \"color\": COLOR_COMPANY,\n", " }\n", - " if node:= nodes.get(row['id_company_to']) is None:\n", - " nodes[row['id_company_to']] = {\n", - " \"id\": row['id_company_to'],\n", - " 'name': row['name_company_to'],\n", - " 'color': COLOR_COMPANY\n", - " } \n", - " edges.append({'from': row['id_company_from'], 'to': row['id_company_to'], 'type': row['relation_type']})\n", - " return nodes, edges\n" + " if node := nodes.get(row[\"id_company_to\"]) is None:\n", + " nodes[row[\"id_company_to\"]] = {\n", + " \"id\": row[\"id_company_to\"],\n", + " \"name\": row[\"name_company_to\"],\n", + " \"color\": COLOR_COMPANY,\n", + " }\n", + " edges.append(\n", + " {\n", + " \"from\": row[\"id_company_from\"],\n", + " \"to\": row[\"id_company_to\"],\n", + " \"type\": row[\"relation_type\"],\n", + " }\n", + " )\n", + " return nodes, edges" ] }, { @@ -1458,7 +1485,9 @@ "metadata": {}, "outputs": [], "source": [ - "tmp_company = filter_relation_with_more_than_one_connection(company_relations, \"id_company_to\", \"id_company_from\")\n", + "tmp_company = filter_relation_with_more_than_one_connection(\n", + " company_relations, \"id_company_to\", \"id_company_from\"\n", + ")\n", "tmp_persons = filter_relation_type(person_relations, \"HAFTENDER_GESELLSCHAFTER\")" ] }, @@ -2257,7 +2286,9 @@ "\n", "measure_type = \"degree\"\n", "measure_vector = {}\n", - "df = pd.DataFrame(columns=[\"degree\", \"eigenvector\", \"degree\", \"betweeness\", \"closeness\", \"pagerank\"])\n", + "df = pd.DataFrame(\n", + " columns=[\"degree\", \"eigenvector\", \"degree\", \"betweeness\", \"closeness\", \"pagerank\"]\n", + ")\n", "\n", "# if measure_type == \"eigenvector\":\n", "# measure_vector = nx.eigenvector_centrality(graph)\n", @@ -2275,7 +2306,6 @@ "# df[\"pagerank\"] = measure_vector.values()\n", "# if measure_type == \"average_degree\":\n", "# measure_vector = nx.average_degree_connectivity(graph)\n", - " \n", "\n", "\n", "df[\"eigenvector\"] = nx.eigenvector_centrality(graph).values()\n", @@ -2301,6 +2331,7 @@ "outputs": [], "source": [ "import igraph as ig\n", + "\n", "# convert to igraph\n", "h = ig.Graph.from_networkx(graph)" ] @@ -2376,7 +2407,7 @@ ], "source": [ "# Nur wenn Pos vorher gesetzt wurde\n", - "pos2 = nx.get_node_attributes(graph,'pos')\n", + "pos2 = nx.get_node_attributes(graph, \"pos\")\n", "print(pos2)" ] }, @@ -2411,6 +2442,7 @@ "outputs": [], "source": [ "import plotly.graph_objects as go\n", + "\n", "edge_x = []\n", "edge_y = []\n", "\n", @@ -2427,25 +2459,31 @@ " edge_y.append(y1)\n", " edge_y.append(None)\n", "\n", - " # edge_weight_x.append(x1 + x1 - x0) \n", + " # edge_weight_x.append(x1 + x1 - x0)\n", " # edge_weight_y.append(y1 + y1 - y0)\n", - " # edge_weight_x.append(x0 + x0 - x1) \n", + " # edge_weight_x.append(x0 + x0 - x1)\n", " # edge_weight_y.append(y0 + y0 - y1)\n", " edge_weight_x.append(x0 + ((x1 - x0) / 2))\n", " edge_weight_y.append(y0 + ((y1 - y0) / 2))\n", "\n", "edge_trace = go.Scatter(\n", - " x=edge_x, y=edge_y,\n", - " line=dict(width=0.5, color='#888'),\n", - " hoverinfo='none',\n", - " mode='lines')\n", + " x=edge_x,\n", + " y=edge_y,\n", + " line=dict(width=0.5, color=\"#888\"),\n", + " hoverinfo=\"none\",\n", + " mode=\"lines\",\n", + ")\n", + "\n", + "edge_weights_trace = go.Scatter(\n", + " x=edge_weight_x,\n", + " y=edge_weight_y,\n", + " mode=\"text\",\n", + " marker_size=1,\n", + " text=[0.45, 0.7, 0.34],\n", + " textposition=\"top center\",\n", + " hovertemplate=\"weight: %{text}\",\n", + ")\n", "\n", - "edge_weights_trace = go.Scatter(x=edge_weight_x,y= edge_weight_y, mode='text',\n", - " marker_size=1,\n", - " text=[0.45, 0.7, 0.34],\n", - " textposition='top center',\n", - " hovertemplate='weight: %{text}')\n", - " \n", "\n", "node_x = []\n", "node_y = []\n", @@ -2455,26 +2493,26 @@ " node_y.append(y)\n", "\n", "node_trace = go.Scatter(\n", - " x=node_x, y=node_y,\n", - " mode='markers',\n", - " hoverinfo='text',\n", + " x=node_x,\n", + " y=node_y,\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", " marker=dict(\n", " showscale=True,\n", " # colorscale options\n", " #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |\n", " #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |\n", " #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |\n", - " colorscale='YlGnBu',\n", + " colorscale=\"YlGnBu\",\n", " reversescale=True,\n", " color=[],\n", " size=10,\n", " colorbar=dict(\n", - " thickness=15,\n", - " title='Node Connections',\n", - " xanchor='left',\n", - " titleside='right'\n", + " thickness=15, title=\"Node Connections\", xanchor=\"left\", titleside=\"right\"\n", " ),\n", - " line_width=2))" + " line_width=2,\n", + " ),\n", + ")" ] }, { @@ -2511,8 +2549,8 @@ " node_adjacencies.append(len(adjacencies[1]))\n", " # node_text.append('# of connections: '+str(len(adjacencies[1])))\n", " # node_adjacencies.append(nodes[node].color)\n", - " node_text.append('# of connections: '+str(len(adjacencies[1])))\n", - " \n", + " node_text.append(\"# of connections: \" + str(len(adjacencies[1])))\n", + "\n", "print(node_adjacencies)\n", "# node_trace.marker.color = node_adjacencies\n", "# node_trace.text = node_text\n", @@ -2543,13 +2581,12 @@ } ], "source": [ - "#Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters!\n", + "# Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters!\n", "colors = list(nx.get_node_attributes(graph, \"color\").values())\n", "\n", "node_names = []\n", "for key, value in nodes.items():\n", - " \n", - " if 'name' in value.keys():\n", + " if \"name\" in value.keys():\n", " node_names.append(value[\"name\"])\n", " else:\n", " node_names.append(value[\"firstname\"] + \" \" + value[\"lastname\"])\n", @@ -2561,8 +2598,8 @@ "\n", "node_trace.marker.color = colors\n", "node_trace.text = node_names\n", - "print(list(df[\"eigenvector\"]*100))\n", - "node_trace.marker.size = list(df[\"eigenvector\"]*100)" + "print(list(df[\"eigenvector\"] * 100))\n", + "node_trace.marker.size = list(df[\"eigenvector\"] * 100)" ] }, { @@ -12520,21 +12557,28 @@ } ], "source": [ - "fig = go.Figure(data=[edge_trace, edge_weights_trace, node_trace],\n", - " layout=go.Layout(\n", - " title='
Network graph made with Python',\n", - " titlefont_size=16,\n", - " showlegend=False,\n", - " hovermode='closest',\n", - " margin=dict(b=20,l=5,r=5,t=40),\n", - " annotations=[ dict(\n", - " text=\"Python code: https://plotly.com/ipython-notebooks/network-graphs/\",\n", - " showarrow=False,\n", - " xref=\"paper\", yref=\"paper\",\n", - " x=0.005, y=-0.002 ) ],\n", - " xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", - " yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))\n", - " )\n", + "fig = go.Figure(\n", + " data=[edge_trace, edge_weights_trace, node_trace],\n", + " layout=go.Layout(\n", + " title=\"
Network graph made with Python\",\n", + " titlefont_size=16,\n", + " showlegend=False,\n", + " hovermode=\"closest\",\n", + " margin=dict(b=20, l=5, r=5, t=40),\n", + " annotations=[\n", + " dict(\n", + " text=\"Python code: https://plotly.com/ipython-notebooks/network-graphs/\",\n", + " showarrow=False,\n", + " xref=\"paper\",\n", + " yref=\"paper\",\n", + " x=0.005,\n", + " y=-0.002,\n", + " )\n", + " ],\n", + " xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", + " yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),\n", + " ),\n", + ")\n", "fig.show()" ] }, @@ -13219,6 +13263,7 @@ ], "source": [ "import numpy as np\n", + "\n", "# Extract node and edge positions from the layout\n", "node_xyz = np.array([pos[v] for v in sorted(graph)])\n", "edge_xyz = np.array([(pos[u], pos[v]) for u, v in graph.edges()])\n", @@ -13234,6 +13279,7 @@ "outputs": [], "source": [ "import plotly.graph_objects as go\n", + "\n", "edge_x = []\n", "edge_y = []\n", "edge_z = []\n", @@ -13257,23 +13303,22 @@ " edge_z.append(z1)\n", " # edge_z.append(z2)\n", "\n", - " # edge_weight_x.append(x1 + x1 - x0) \n", + " # edge_weight_x.append(x1 + x1 - x0)\n", " # edge_weight_y.append(y1 + y1 - y0)\n", - " # edge_weight_x.append(x0 + x0 - x1) \n", + " # edge_weight_x.append(x0 + x0 - x1)\n", " # edge_weight_y.append(y0 + y0 - y1)\n", " # edge_weight_x.append(x0 + ((x1 - x0) / 2))\n", " # edge_weight_y.append(y0 + ((y1 - y0) / 2))\n", "\n", "\n", - "\n", - "\n", - "edge_trace=go.Scatter3d(x=edge_x,\n", - " y=edge_y,\n", - " z=edge_z,\n", - " mode='lines',\n", - " line=dict(color='rgb(125,125,125)', width=1),\n", - " hoverinfo='none'\n", - " )\n", + "edge_trace = go.Scatter3d(\n", + " x=edge_x,\n", + " y=edge_y,\n", + " z=edge_z,\n", + " mode=\"lines\",\n", + " line=dict(color=\"rgb(125,125,125)\", width=1),\n", + " hoverinfo=\"none\",\n", + ")\n", "\n", "node_x = []\n", "node_y = []\n", @@ -13284,58 +13329,58 @@ " node_y.append(y)\n", " node_z.append(z)\n", "\n", - "node_trace=go.Scatter3d(x=node_x,\n", - " y=node_y,\n", - " z=node_z,\n", - " mode='markers',\n", - " name='actors',\n", - " marker=dict(symbol='circle',\n", - " size=6,\n", - " color=\"blue\",\n", - " colorscale='Viridis',\n", - " line=dict(color='rgb(50,50,50)', width=0.5)\n", - " ),\n", - " # text=labels,\n", - " hoverinfo='text'\n", - " )\n", + "node_trace = go.Scatter3d(\n", + " x=node_x,\n", + " y=node_y,\n", + " z=node_z,\n", + " mode=\"markers\",\n", + " name=\"actors\",\n", + " marker=dict(\n", + " symbol=\"circle\",\n", + " size=6,\n", + " color=\"blue\",\n", + " colorscale=\"Viridis\",\n", + " line=dict(color=\"rgb(50,50,50)\", width=0.5),\n", + " ),\n", + " # text=labels,\n", + " hoverinfo=\"text\",\n", + ")\n", "\n", - "axis=dict(showbackground=False,\n", - " showline=False,\n", - " zeroline=False,\n", - " showgrid=False,\n", - " showticklabels=False,\n", - " title=''\n", - " )\n", + "axis = dict(\n", + " showbackground=False,\n", + " showline=False,\n", + " zeroline=False,\n", + " showgrid=False,\n", + " showticklabels=False,\n", + " title=\"\",\n", + ")\n", "\n", "layout = go.Layout(\n", - " title=\"Network of coappearances of characters in Victor Hugo's novel
Les Miserables (3D visualization)\",\n", - " width=1000,\n", - " height=1000,\n", - " showlegend=False,\n", - " scene=dict(\n", - " xaxis=dict(axis),\n", - " yaxis=dict(axis),\n", - " zaxis=dict(axis),\n", - " ),\n", - " margin=dict(\n", - " t=100\n", + " title=\"Network of coappearances of characters in Victor Hugo's novel
Les Miserables (3D visualization)\",\n", + " width=1000,\n", + " height=1000,\n", + " showlegend=False,\n", + " scene=dict(\n", + " xaxis=dict(axis),\n", + " yaxis=dict(axis),\n", + " zaxis=dict(axis),\n", " ),\n", - " hovermode='closest',\n", + " margin=dict(t=100),\n", + " hovermode=\"closest\",\n", " annotations=[\n", - " dict(\n", - " showarrow=False,\n", + " dict(\n", + " showarrow=False,\n", " text=\"Data source: [1] miserables.json\",\n", - " xref='paper',\n", - " yref='paper',\n", + " xref=\"paper\",\n", + " yref=\"paper\",\n", " x=0,\n", " y=0.1,\n", - " xanchor='left',\n", - " yanchor='bottom',\n", - " font=dict(\n", - " size=14\n", - " )\n", - " )\n", - " ], )" + " xanchor=\"left\",\n", + " yanchor=\"bottom\",\n", + " font=dict(size=14),\n", + " )\n", + " ],\n", + ")" ] }, { @@ -13353,13 +13398,12 @@ } ], "source": [ - "#Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters!\n", + "# Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters!\n", "colors = list(nx.get_node_attributes(graph, \"color\").values())\n", "\n", "node_names = []\n", "for key, value in nodes.items():\n", - " \n", - " if 'name' in value.keys():\n", + " if \"name\" in value.keys():\n", " node_names.append(value[\"name\"])\n", " else:\n", " node_names.append(value[\"firstname\"] + \" \" + value[\"lastname\"])\n", @@ -13396,9 +13440,9 @@ "edge_colors = []\n", "for row in edges:\n", " if row[\"type\"] == \"HAFTENDER_GESELLSCHAFTER\":\n", - " edge_colors.append('rgb(255,0,0)')\n", + " edge_colors.append(\"rgb(255,0,0)\")\n", " else:\n", - " edge_colors.append('rgb(255,105,180)')\n", + " edge_colors.append(\"rgb(255,105,180)\")\n", "print(edge_colors)\n", "edge_trace.line = dict(color=edge_colors, width=2)" ] @@ -22038,9 +22082,9 @@ } ], "source": [ - "# edge_trace, \n", - "data=[edge_trace, node_trace]\n", - "fig=go.Figure(data=data, layout=layout)\n", + "# edge_trace,\n", + "data = [edge_trace, node_trace]\n", + "fig = go.Figure(data=data, layout=layout)\n", "\n", "fig.show()" ] diff --git a/src/aki_prj23_transparenzregister/utils/networkx/tmp.html b/src/aki_prj23_transparenzregister/utils/networkx/archive/tmp.html similarity index 99% rename from src/aki_prj23_transparenzregister/utils/networkx/tmp.html rename to src/aki_prj23_transparenzregister/utils/networkx/archive/tmp.html index dc4e0ac..d4e1a2c 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/tmp.html +++ b/src/aki_prj23_transparenzregister/utils/networkx/archive/tmp.html @@ -1,275 +1,275 @@ - - - - - - - - - -
-

-
- - - - - - -
-

-
- - - - - -
- - -
-
- - -
-
-
0%
-
-
-
-
-
- - -
- - - - - \ No newline at end of file + + + + + + + + + +
+

+
+ + + + + + +
+

+
+ + + + + +
+ + +
+
+ + +
+
+
0%
+
+
+
+
+
+ + +
+ + + + + diff --git a/src/aki_prj23_transparenzregister/utils/networkx/network_2d.py b/src/aki_prj23_transparenzregister/utils/networkx/network_2d.py index a7fe3f3..39da7f3 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/network_2d.py +++ b/src/aki_prj23_transparenzregister/utils/networkx/network_2d.py @@ -1,128 +1,133 @@ +"""This Module contains the Method to create a 2D Network Graph with NetworkX.""" import networkx as nx import pandas as pd import plotly.graph_objects as go -def initialize_network(edges: list, nodes: list): - # create edges from dataframe - df_edges = pd.DataFrame(edges) - graph = nx.from_pandas_edgelist(df_edges, source="from", target="to", edge_attr="type") - # update node attributes from dataframe - nx.set_node_attributes(graph, nodes) +def create_2d_graph( + graph: nx.Graph, nodes: dict, edges: list, metrics: pd.DataFrame, metric: str | None +) -> go.Figure: + """This Method creates a 2d Network in Plotly with a Scatter Graph and retuns it. - metrices = pd.DataFrame(columns=["degree", "eigenvector", "betweeness", "closeness", "pagerank"]) - - metrices["eigenvector"] = nx.eigenvector_centrality(graph).values() - metrices["degree"] = nx.degree_centrality(graph).values() - metrices["betweeness"] = nx.betweenness_centrality(graph).values() - metrices["closeness"] = nx.closeness_centrality(graph).values() - metrices["pagerank"] = nx.pagerank(graph).values() - - return graph, metrices - -def create_2d_graph(graph, nodes, edges,metrices, metric): - edge_x = [] - edge_y = [] + Args: + graph (_type_): NetworkX Graph. + nodes (_type_): List of Nodes + edges (_type_): List of Edges + metrics (_type_): DataFrame with the MEtrics + metric (_type_): Selected Metric + Returns: + _type_: Plotly Figure + """ + # Set 2D Layout pos = nx.spring_layout(graph) + # Initialize Variables to set the Position of the Edges. + edge_x = [] + edge_y = [] + # Initialize Node Position Variables. + node_x = [] + node_y = [] + # Initialize Position Variables for the Description Text of the edges. edge_weight_x = [] edge_weight_y = [] - G = graph - for edge in G.edges(): + + # Getting the Positions from NetworkX and assign them to the variables. + for edge in graph.edges(): x0, y0 = pos[edge[0]] x1, y1 = pos[edge[1]] edge_x.append(x0) edge_x.append(x1) edge_x.append(None) + edge_y.append(y0) edge_y.append(y1) edge_y.append(None) - # edge_weight_x.append(x1 + x1 - x0) - # edge_weight_y.append(y1 + y1 - y0) - # edge_weight_x.append(x0 + x0 - x1) - # edge_weight_y.append(y0 + y0 - y1) edge_weight_x.append(x0 + ((x1 - x0) / 2)) edge_weight_y.append(y0 + ((y1 - y0) / 2)) - + edge_weight_y.append(None) + # Add the Edges to the scatter plot according to their Positions. edge_trace = go.Scatter( - x=edge_x, y=edge_y, - line=dict(width=0.5, color='#888'), - hoverinfo='none', - mode='lines') + x=edge_x, + y=edge_y, + line={"width": 0.5, "color": "#888"}, + hoverinfo="none", + mode="lines", + ) + # Add the Edgedescriptiontext to the scatter plot according to its Position. + edge_weights_trace = go.Scatter( + x=edge_weight_x, + y=edge_weight_y, + mode="text", + marker_size=1, + text=[0.45, 0.7, 0.34], + textposition="top center", + hovertemplate="weight: %{text}", + ) - edge_weights_trace = go.Scatter(x=edge_weight_x,y= edge_weight_y, mode='text', - marker_size=1, - text=[0.45, 0.7, 0.34], - textposition='top center', - hovertemplate='weight: %{text}') - - - node_x = [] - node_y = [] - for node in G.nodes(): + # Getting the Positions from NetworkX and assign it to the variables. + for node in graph.nodes(): x, y = pos[node] node_x.append(x) node_y.append(y) - + # Add the Nodes to the scatter plot according to their Positions. node_trace = go.Scatter( - x=node_x, y=node_y, - mode='markers', - hoverinfo='text', - marker=dict( - showscale=True, - colorscale='YlGnBu', - reversescale=True, - color=[], - size=10, - colorbar=dict( - thickness=15, - title='Node Connections', - xanchor='left', - titleside='right' - ), - line_width=2)) - - #Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters! - colors = list(nx.get_node_attributes(graph, "color").values()) + x=node_x, + y=node_y, + mode="markers", + hoverinfo="text", + marker={ + "showscale": True, + "colorscale": "YlGnBu", + "reversescale": True, + "color": [], + "size": 10, + "colorbar": { + "thickness": 15, + "title": "Node Connections", + "xanchor": "left", + "titleside": "right", + }, + "line_width": 2, + }, + ) + # Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters! + colors = list(nx.get_node_attributes(graph, "color").values()) + # Get the Node Text node_names = [] for key, value in nodes.items(): - - if 'name' in value.keys(): + if "name" in value: node_names.append(value["name"]) else: node_names.append(value["firstname"] + " " + value["lastname"]) - - + # Add Color and Names to the Scatter Plot. node_trace.marker.color = colors node_trace.text = node_names - if metric != None: - node_trace.marker.size = list(metrices[metric]*500) - # print(list(metrices[metric]*500)) - + # Highlight the Node Size in regards to the selected Metric. + if metric is not None: + node_trace.marker.size = list(metrics[metric] * 500) + # Add Relation_Type as a Descriptin for the edges. edge_type_list = [] - for row in edges: edge_type_list.append(row["type"]) - + edge_weights_trace.text = edge_type_list - return go.Figure(data=[edge_trace, edge_weights_trace, node_trace], - layout=go.Layout( - title='
Network graph made with Python', - titlefont_size=16, - showlegend=False, - hovermode='closest', - margin=dict(b=20,l=5,r=5,t=40), - annotations=[ dict( - text="Python code: https://plotly.com/ipython-notebooks/network-graphs/", - showarrow=False, - xref="paper", yref="paper", - x=0.005, y=-0.002 ) ], - xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), - yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)) - ) \ No newline at end of file + # Return the Plotly Figure + return go.Figure( + data=[edge_trace, edge_weights_trace, node_trace], + layout=go.Layout( + title="
Network graph made with Python", + titlefont_size=16, + showlegend=False, + hovermode="closest", + margin={"b": 20, "l": 5, "r": 5, "t": 20}, + # annotations=, + xaxis={"showgrid": False, "zeroline": False, "showticklabels": False}, + yaxis={"showgrid": False, "zeroline": False, "showticklabels": False}, + ), + ) diff --git a/src/aki_prj23_transparenzregister/utils/networkx/network_3d.py b/src/aki_prj23_transparenzregister/utils/networkx/network_3d.py index c511cd6..980e98b 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/network_3d.py +++ b/src/aki_prj23_transparenzregister/utils/networkx/network_3d.py @@ -1,33 +1,38 @@ +"""This Module contains the Method to create a 3D Network Graph with NetworkX.""" import networkx as nx import pandas as pd import plotly.graph_objects as go -def initialize_network(edges: list, nodes: list): - # create edges from dataframe - df_edges = pd.DataFrame(edges) - graph = nx.from_pandas_edgelist(df_edges, source="from", target="to", edge_attr="type") - # update node attributes from dataframe - nx.set_node_attributes(graph, nodes) +def create_3d_graph( + graph: nx.Graph, nodes: dict, edges: list, metrics: pd.DataFrame, metric: str | None +) -> go.Figure: + """This Method creates a 3D Network in Plotly with a Scatter Graph and retuns it. - metrices = pd.DataFrame(columns=["degree", "eigenvector", "betweeness", "closeness", "pagerank"]) + Args: + graph (_type_): NetworkX Graph. + nodes (_type_): List of Nodes + edges (_type_): List of Edges + metrics (_type_): DataFrame with the MEtrics + metric (_type_): Selected Metric - metrices["eigenvector"] = nx.eigenvector_centrality(graph).values() - metrices["degree"] = nx.degree_centrality(graph).values() - metrices["betweeness"] = nx.betweenness_centrality(graph).values() - metrices["closeness"] = nx.closeness_centrality(graph).values() - metrices["pagerank"] = nx.pagerank(graph).values() + Returns: + _type_: Plotly Figure + """ + # 3d spring layout + pos = nx.spring_layout(graph, dim=3, seed=779) - return graph, metrices - -def create_3d_graph(graph, nodes, edges,metrices, metric): + # Initialize Variables to set the Position of the Edges. edge_x = [] edge_y = [] edge_z = [] - # 3d spring layout - pos = nx.spring_layout(graph, dim=3, seed=779) + # Initialize Node Position Variables. + node_x = [] + node_y = [] + node_z = [] + # Getting the Positions from NetworkX and assign them to the variables. for edge in graph.edges(): x0, y0, z0 = pos[edge[0]] x1, y1, z1 = pos[edge[1]] @@ -41,102 +46,101 @@ def create_3d_graph(graph, nodes, edges,metrices, metric): edge_z.append(z0) edge_z.append(z1) - edge_trace=go.Scatter3d(x=edge_x, - y=edge_y, - z=edge_z, - mode='lines', - line=dict(color='rgb(125,125,125)', width=1), - hoverinfo='none' - ) - - node_x = [] - node_y = [] - node_z = [] + # Add the Edges to the scatter plot according to their Positions. + edge_trace = go.Scatter3d( + x=edge_x, + y=edge_y, + z=edge_z, + mode="lines", + line={"color": "rgb(125,125,125)", "width": 1}, + hoverinfo="none", + ) + # Getting the Positions from NetworkX and assign it to the variables. for node in graph.nodes(): x, y, z = pos[node] node_x.append(x) node_y.append(y) node_z.append(z) - node_trace=go.Scatter3d(x=node_x, - y=node_y, - z=node_z, - mode='markers', - name='actors', - marker=dict(symbol='circle', - size=6, - color="blue", - colorscale='Viridis', - line=dict(color='rgb(50,50,50)', width=0.5) - ), - # text=labels, - hoverinfo='text' - ) + # Add the Nodes to the scatter plot according to their Positions. + node_trace = go.Scatter3d( + x=node_x, + y=node_y, + z=node_z, + mode="markers", + name="actors", + marker={ + "symbol": "circle", + "size": 6, + "color": "blue", + "colorscale": "Viridis", + "line": {"color": "rgb(50,50,50)", "width": 0.5}, + }, + # text=labels, + hoverinfo="text", + ) - axis=dict(showbackground=False, - showline=False, - zeroline=False, - showgrid=False, - showticklabels=False, - title='' - ) + axis = { + "showbackground": False, + "showline": False, + "zeroline": False, + "showgrid": False, + "showticklabels": False, + "title": "", + } layout = go.Layout( - title="Social Graph", - - showlegend=False, - scene=dict( - xaxis=dict(axis), - yaxis=dict(axis), - zaxis=dict(axis), - ), - margin=dict( - t=10 - ), - hovermode='closest', + title="Social Graph", + showlegend=False, + scene={ + "xaxis": dict(axis), + "yaxis": dict(axis), + "zaxis": dict(axis), + }, + margin={"t": 10}, + hovermode="closest", annotations=[ - dict( - showarrow=False, - text="Companies (Blue) & Person (Red) Relation", - xref='paper', - yref='paper', - x=0, - y=0.1, - xanchor='left', - yanchor='bottom', - font=dict( - size=14 - ) - ) - ], ) + { + "showarrow": False, + "text": "Companies (Blue) & Person (Red) Relation", + "xref": "paper", + "yref": "paper", + "x": 0, + "y": 0.1, + "xanchor": "left", + "yanchor": "bottom", + "font": {"size": 14}, + } + ], + ) - #Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters! + # Set Color by using the nodes DataFrame with its Color Attribute. The sequence matters! colors = list(nx.get_node_attributes(graph, "color").values()) node_names = [] for key, value in nodes.items(): - - if 'name' in value.keys(): + if "name" in value: node_names.append(value["name"]) else: node_names.append(value["firstname"] + " " + value["lastname"]) - + # Add Color and Names to the Scatter Plot. node_trace.marker.color = colors node_trace.text = node_names - if metric != None: - node_trace.marker.size = list(metrices[metric]*500) - print("Test") + # Highlight the Node Size in regards to the selected Metric. + if metric is not None: + node_trace.marker.size = list(metrics[metric] * 500) + # Set the Color and width of Edges for better highlighting. edge_colors = [] for row in edges: if row["type"] == "HAFTENDER_GESELLSCHAFTER": - edge_colors.append('rgb(255,0,0)') + edge_colors.append("rgb(255,0,0)") else: - edge_colors.append('rgb(255,105,180)') - edge_trace.line = dict(color=edge_colors, width=2) + edge_colors.append("rgb(255,105,180)") + edge_trace.line = {"color": edge_colors, "width": 2} - - data=[edge_trace, node_trace] + # Return the Plotly Figure + data = [edge_trace, node_trace] return go.Figure(data=data, layout=layout) diff --git a/src/aki_prj23_transparenzregister/utils/networkx/network_base.py b/src/aki_prj23_transparenzregister/utils/networkx/network_base.py new file mode 100644 index 0000000..a30874b --- /dev/null +++ b/src/aki_prj23_transparenzregister/utils/networkx/network_base.py @@ -0,0 +1,36 @@ +"""This Module has a Method to initialize a Network with NetworkX which can be used for 2D and 3D Graphs.""" +import networkx as nx +import pandas as pd + + +def initialize_network(edges: list, nodes: dict) -> tuple[nx.Graph, pd.DataFrame]: + """This Method creates a Network from the Framework NetworkX with the help of a Node and Edge List. Furthemore it creates a DataFrame with the most important Metrics. + + Args: + edges (list): List with the connections between Nodes. + nodes (list): List with all Nodes. + + Returns: + Graph: Plotly Figure + Metrices: DataFrame with Metrics + """ + # create edge dataframe + df_edges = pd.DataFrame(edges) + graph = nx.from_pandas_edgelist( + df_edges, source="from", target="to", edge_attr="type" + ) + + # update node attributes from dataframe + nx.set_node_attributes(graph, nodes) + + # Create a DataFrame with all Metrics + metrices = pd.DataFrame( + columns=["degree", "eigenvector", "betweeness", "closeness", "pagerank"] + ) + metrices["eigenvector"] = nx.eigenvector_centrality(graph).values() + metrices["degree"] = nx.degree_centrality(graph).values() + metrices["betweeness"] = nx.betweenness_centrality(graph).values() + metrices["closeness"] = nx.closeness_centrality(graph).values() + metrices["pagerank"] = nx.pagerank(graph).values() + + return graph, metrices diff --git a/src/aki_prj23_transparenzregister/utils/networkx/networkx_data.py b/src/aki_prj23_transparenzregister/utils/networkx/networkx_data.py index 9641955..8f43023 100644 --- a/src/aki_prj23_transparenzregister/utils/networkx/networkx_data.py +++ b/src/aki_prj23_transparenzregister/utils/networkx/networkx_data.py @@ -1,11 +1,12 @@ -from aki_prj23_transparenzregister.utils.sql import connector, entities -from aki_prj23_transparenzregister.config.config_providers import JsonFileConfigProvider +"""Module to receive and filter Data for working with NetworkX.""" import pandas as pd from sqlalchemy.orm import aliased -import pandas as pd -from sqlalchemy import func, text + +from aki_prj23_transparenzregister.config.config_providers import JsonFileConfigProvider +from aki_prj23_transparenzregister.utils.sql import connector, entities from aki_prj23_transparenzregister.utils.sql.connector import get_session +# Gets the Session Key for the DB Connection. session = get_session(JsonFileConfigProvider("secrets.json")) # Alias for Company table for the base company @@ -14,54 +15,68 @@ to_company = aliased(entities.Company, name="to_company") # Alias for Company table for the head company from_company = aliased(entities.Company, name="from_company") + def find_all_company_relations() -> pd.DataFrame: - """_summary_ + """_summary_. Returns: pd.DataFrame: _description_ """ session = connector.get_session(JsonFileConfigProvider("./secrets.json")) - query_companies = session.query(entities.Company) #.all() - query_relations = session.query(entities.CompanyRelation) # .all() + query_companies = session.query(entities.Company) # .all() + query_relations = session.query(entities.CompanyRelation) # .all() companies_df: pd.DataFrame = pd.read_sql(str(query_companies), session.bind) # type: ignore companies_relations_df: pd.DataFrame = pd.read_sql(str(query_relations), session.bind) # type: ignore - companies_relations_df = companies_relations_df[["relation_id","company_relation_company2_id"]] + companies_relations_df = companies_relations_df[ + ["relation_id", "company_relation_company2_id"] + ] company_name = [] connected_company_name = [] companies_relations_df = companies_relations_df.head() - for _, row in companies_relations_df.iterrows(): - company_name.append(companies_df.loc[companies_df["company_id"] == row["relation_id"]]["company_name"].values[0]) - connected_company_name.append(companies_df.loc[companies_df["company_id"] == row["company_relation_company2_id"]]["company_name"].values[0]) - + for _, row in companies_relations_df.iterrows(): + company_name.append( + companies_df.loc[companies_df["company_id"] == row["relation_id"]][ + "company_name" + ].values[0] + ) + connected_company_name.append( + companies_df.loc[ + companies_df["company_id"] == row["company_relation_company2_id"] + ]["company_name"].values[0] + ) + companies_relations_df["company_name"] = company_name companies_relations_df["connected_company_name"] = connected_company_name - + return companies_relations_df + def find_top_companies() -> pd.DataFrame: - """_summary_ + """_summary_. Returns: pd.DataFrame: _description_ """ session = connector.get_session(JsonFileConfigProvider("./secrets.json")) - query_companies = session.query(entities.Company) #.all() + query_companies = session.query(entities.Company) # .all() companies_df: pd.DataFrame = pd.read_sql(str(query_companies), session.bind) # type: ignore companies_df = companies_df.head() companies_df = companies_df[["company_name"]] - companies_df["Platzierung"] = [1,2,3,4,5] - companies_df["Umsatz M€"] = [1,2,3,4,5] - companies_df = companies_df[['Platzierung', 'company_name', 'Umsatz M€']] - # print(companies_df) - return companies_df + companies_df["Platzierung"] = [1, 2, 3, 4, 5] + companies_df["Umsatz M€"] = [1, 2, 3, 4, 5] + return companies_df[["Platzierung", "company_name", "Umsatz M€"]] +def get_all_company_relations() -> pd.DataFrame: + """This Methods makes a Database Request for all Companies and their relations, modifies the ID Column and returns the Result as an DataFrame. -def get_all_company_relations(): + Returns: + DataFrame: DataFrame with all Relations between Companies. + """ # Query to fetch relations between companies relations_company_query = ( session.query( @@ -83,12 +98,22 @@ def get_all_company_relations(): str(relations_company_query) company_relations = pd.read_sql_query(str(relations_company_query), session.bind) - company_relations['id_company_from'] = company_relations['id_company_from'].apply(lambda x: f"c_{x}") - company_relations['id_company_to'] = company_relations['id_company_to'].apply(lambda x: f"c_{x}") + company_relations["id_company_from"] = company_relations["id_company_from"].apply( + lambda x: f"c_{x}" + ) + company_relations["id_company_to"] = company_relations["id_company_to"].apply( + lambda x: f"c_{x}" + ) return company_relations -def get_all_person_relations(): + +def get_all_person_relations() -> pd.DataFrame: + """This Methods makes a Database Request for all Persons and their relations, modifies the ID Column and returns the Result as an DataFrame. + + Returns: + DataFrame: DataFrame with all Relations between Persons and Companies. + """ relations_person_query = ( session.query( entities.Company.id.label("id_company"), @@ -110,83 +135,129 @@ def get_all_person_relations(): ) person_relations = pd.read_sql_query(str(relations_person_query), session.bind) - person_relations['id_company'] = person_relations['id_company'].apply(lambda x: f"c_{x}") - person_relations['id_person'] = person_relations['id_person'].apply(lambda x: f"p_{x}") + person_relations["id_company"] = person_relations["id_company"].apply( + lambda x: f"c_{x}" + ) + person_relations["id_person"] = person_relations["id_person"].apply( + lambda x: f"p_{x}" + ) - return person_relations -def filter_relation_type(df: pd.DataFrame, selected_relation_type): - df = df.loc[df["relation_type"] == selected_relation_type] - return df +def filter_relation_type( + relation_dataframe: pd.DataFrame, selected_relation_type: str +) -> pd.DataFrame: + """This Method filters the given DataFrame based on the selected Relation Type and returns it. + + Args: + relation_dataframe (pd.DataFrame): DataFrame must contain a column named "relation_type". + selected_relation_type (str): String with the filter value. + + Returns: + relation_dataframe (pd.DataFrame): The filtered DataFrame which now only contains entries with the selected Relation Type. + """ + return relation_dataframe.loc[ + relation_dataframe["relation_type"] == selected_relation_type + ] -def filter_relation_with_more_than_one_connection(df: pd.DataFrame, id_column_name_to, id_column_name_from): - # print(df.columns.values) - tmp_df = pd.DataFrame(columns= df.columns.values) - # print(tmp_df) - for _index, row in df.iterrows(): +def filter_relation_with_more_than_one_connection( + relation_dataframe: pd.DataFrame, id_column_name_to: str, id_column_name_from: str +) -> pd.DataFrame: + """Method to filter all Entries in an DataFrame which has more than one connection. + + Args: + relation_dataframe (pd.DataFrame): _description_ + id_column_name_to (_type_): _description_ + id_column_name_from (_type_): _description_ + + Returns: + relation_dataframe (pd.DataFrame): The DataFrame which now only contains entries with more than one connection. + """ + tmp_df = pd.DataFrame(columns=relation_dataframe.columns.values) + for _index, row in relation_dataframe.iterrows(): count = 0 id = row[id_column_name_to] - for _index_sub, row_sub in df.iterrows(): + for _index_sub, row_sub in relation_dataframe.iterrows(): if id == row_sub[id_column_name_to]: count = count + 1 if id == row_sub[id_column_name_from]: count = count + 1 if count > 1: break - + if count > 1: # tmp_df = pd.concat([tmp_df, pd.DataFrame(row)])+ tmp_df.loc[len(tmp_df)] = row - # print(row) count = 0 else: count = 0 continue - # print(tmp_df) count = 0 return tmp_df -def create_edge_and_node_list(person_relations: pd.DataFrame, company_relations:pd.DataFrame): - nodes = {} - edges = [] +def create_edge_and_node_list( + person_relations: pd.DataFrame, company_relations: pd.DataFrame +) -> tuple[dict, list]: + """In this Method the given DataFrame with the relation will be morphed to Edge and Node lists and enhanced by a coloring for companies and person Nodes. + + Args: + person_relations (pd.DataFrame): _description_ + company_relations (pd.DataFrame): _description_ + + Returns: + _type_: _description_ + """ + nodes: dict = {} + edges: list = [] COLOR_COMPANY = "blue" COLOR_PERSON = "red" # Iterate over person relations for _index, row in person_relations.iterrows(): - if node:= nodes.get(row['id_company']) is None: - nodes[row['id_company']] = { - "id": row['id_company'], - 'name': row['name_company'], - 'color': COLOR_COMPANY + if node := nodes.get(row["id_company"]) is None: + nodes[row["id_company"]] = { + "id": row["id_company"], + "name": row["name_company"], + "color": COLOR_COMPANY, } - if node:= nodes.get(row['id_person']) is None: - nodes[row['id_person']] = { - "id": row['id_person'], - 'firstname': row['firstname'], - 'lastname': row['lastname'], - 'date_of_birth': row['date_of_birth'], - 'color': COLOR_PERSON - } - edges.append({'from': row['id_person'], 'to': row['id_company'], 'type': row['relation_type']}) + if node := nodes.get(row["id_person"]) is None: + nodes[row["id_person"]] = { + "id": row["id_person"], + "firstname": row["firstname"], + "lastname": row["lastname"], + "date_of_birth": row["date_of_birth"], + "color": COLOR_PERSON, + } + edges.append( + { + "from": row["id_person"], + "to": row["id_company"], + "type": row["relation_type"], + } + ) for _index, row in company_relations.iterrows(): - if node:= nodes.get(row['id_company_from']) is None: - nodes[row['id_company_from']] = { - "id": row['id_company_from'], - 'name': row['name_company_from'], - 'color': COLOR_COMPANY + if node := nodes.get(row["id_company_from"]) is None: + nodes[row["id_company_from"]] = { + "id": row["id_company_from"], + "name": row["name_company_from"], + "color": COLOR_COMPANY, } - if node:= nodes.get(row['id_company_to']) is None: - nodes[row['id_company_to']] = { - "id": row['id_company_to'], - 'name': row['name_company_to'], - 'color': COLOR_COMPANY - } - edges.append({'from': row['id_company_from'], 'to': row['id_company_to'], 'type': row['relation_type']}) - return nodes, edges \ No newline at end of file + if node := nodes.get(row["id_company_to"]) is None: + nodes[row["id_company_to"]] = { + "id": row["id_company_to"], + "name": row["name_company_to"], + "color": COLOR_COMPANY, + } + edges.append( + { + "from": row["id_company_from"], + "to": row["id_company_to"], + "type": row["relation_type"], + } + ) + return nodes, edges