Skip to content

Commit ec9dfd9

Browse files
committed
Create Degree Analysis Script
1 parent 7ede8b2 commit ec9dfd9

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

degree_analysis_report.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Degree Analysis Report
2+
**Generated on:** 2025-10-13 12:49:38
3+
4+
## Summary Statistics
5+
- Total Nodes: 418
6+
- Maximum Degree: 18
7+
- Minimum Degree: 1
8+
9+
## Top 10 Nodes by Degree
10+
| Rank | Node | Degree |
11+
|------|-------|---------|
12+
| 1 | We established the initial Q3 monthly roadmap and base expectations of what we want to achieve in sessions. | 18 |
13+
| 2 | Best places to find info: Discord, Meeting Summaries and Quarterly Reports | 18 |
14+
| 3 | All Categories are updated with new information | 18 |
15+
| 4 | What are Quarter 3 maintenance plans? | 18 |
16+
| 5 | GPT is very helpful, providing useful information or triggering thoughts of improvements | 18 |
17+
| 6 | Knowledge Base Proposal seems to be a good document for onboarding | 18 |
18+
| 7 | Uncertain when the time comes to contribute | 18 |
19+
| 8 | We went over the Progress Report, line by line | 18 |
20+
| 9 | Reviewed GitBook, shared update on the [getting started page] (https://ambassadorss-organization.gitbook.io/knowledge-base) | 18 |
21+
| 10 | It's time-consuming to learn about the document context and understand its current relevance for GitBook | 18 |
22+
23+
## Degree Distribution
24+
| Degree | Count of Nodes |
25+
|---------|----------------|
26+
| 1 | 14 |
27+
| 2 | 30 |
28+
| 3 | 56 |
29+
| 4 | 70 |
30+
| 5 | 61 |
31+
| 6 | 48 |
32+
| 7 | 32 |
33+
| 9 | 12 |
34+
| 10 | 22 |
35+
| 11 | 13 |
36+
| 12 | 13 |
37+
| 13 | 28 |
38+
| 18 | 19 |

degree_analysis_to_md.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import json
2+
import requests
3+
import networkx as nx
4+
from itertools import combinations
5+
from collections import Counter
6+
from datetime import datetime
7+
8+
def load_json_remote(url):
9+
"""Load JSON data from a remote URL."""
10+
response = requests.get(url)
11+
response.raise_for_status()
12+
return response.json()
13+
14+
def find_participant_lists(obj):
15+
"""
16+
Recursively find all lists of strings in a JSON-like object.
17+
Returns a list of lists (each list being a potential participant group).
18+
"""
19+
results = []
20+
21+
if isinstance(obj, dict):
22+
for value in obj.values():
23+
results.extend(find_participant_lists(value))
24+
elif isinstance(obj, list):
25+
# Check if this list looks like a participant list (all strings)
26+
if all(isinstance(x, str) for x in obj) and len(obj) > 1:
27+
results.append(obj)
28+
else:
29+
for item in obj:
30+
results.extend(find_participant_lists(item))
31+
32+
return results
33+
34+
def build_coattendance_graph(meetings):
35+
"""Build an undirected co-attendance graph from all detected participant lists."""
36+
G = nx.Graph()
37+
38+
for meeting in meetings:
39+
participant_lists = find_participant_lists(meeting)
40+
# Merge all string lists found in this record
41+
participants = set()
42+
for lst in participant_lists:
43+
participants.update(lst)
44+
45+
if len(participants) < 2:
46+
continue
47+
48+
for p in participants:
49+
G.add_node(p)
50+
for u, v in combinations(participants, 2):
51+
if G.has_edge(u, v):
52+
G[u][v]['weight'] += 1
53+
else:
54+
G.add_edge(u, v, weight=1)
55+
56+
return G
57+
58+
def degree_analysis(G):
59+
"""Compute degree metrics for the graph."""
60+
degree_dict = dict(G.degree())
61+
degree_counts = Counter(degree_dict.values())
62+
return degree_dict, degree_counts
63+
64+
def write_markdown_report(degree_dict, degree_counts, output_file):
65+
"""Write results to a Markdown file."""
66+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
67+
with open(output_file, "w", encoding="utf-8") as f:
68+
f.write(f"# Degree Analysis Report\n")
69+
f.write(f"**Generated on:** {timestamp}\n\n")
70+
71+
# Summary
72+
f.write("## Summary Statistics\n")
73+
f.write(f"- Total Nodes: {len(degree_dict)}\n")
74+
f.write(f"- Maximum Degree: {max(degree_dict.values()) if degree_dict else 0}\n")
75+
f.write(f"- Minimum Degree: {min(degree_dict.values()) if degree_dict else 0}\n\n")
76+
77+
# Top 10 nodes
78+
f.write("## Top 10 Nodes by Degree\n")
79+
f.write("| Rank | Node | Degree |\n|------|-------|---------|\n")
80+
for i, (node, deg) in enumerate(sorted(degree_dict.items(), key=lambda x: x[1], reverse=True)[:10], 1):
81+
f.write(f"| {i} | {node} | {deg} |\n")
82+
f.write("\n")
83+
84+
# Degree distribution
85+
f.write("## Degree Distribution\n")
86+
f.write("| Degree | Count of Nodes |\n|---------|----------------|\n")
87+
for degree, count in sorted(degree_counts.items()):
88+
f.write(f"| {degree} | {count} |\n")
89+
90+
print(f"✅ Markdown report saved to: {output_file}")
91+
92+
def main():
93+
url = "https://raw.githubusercontent.com/SingularityNET-Archive/SingularityNET-Archive/refs/heads/main/Data/Snet-Ambassador-Program/Meeting-Summaries/2025/meeting-summaries-array.json"
94+
output_file = "degree_analysis_report.md"
95+
96+
print("📡 Fetching data from remote source...")
97+
data = load_json_remote(url)
98+
print(f"✅ Downloaded {len(data)} meeting records.")
99+
100+
print("🔍 Detecting participant lists recursively...")
101+
G = build_coattendance_graph(data)
102+
103+
if len(G.nodes) == 0:
104+
print("⚠️ No participant lists found — please check JSON structure manually.")
105+
return
106+
107+
print(f"📊 Built graph with {len(G.nodes)} nodes and {len(G.edges)} edges.")
108+
109+
degree_dict, degree_counts = degree_analysis(G)
110+
write_markdown_report(degree_dict, degree_counts, output_file)
111+
112+
if __name__ == "__main__":
113+
main()
114+

0 commit comments

Comments
 (0)