@@ -366,6 +366,7 @@ def write_html_report(
366366 <meta name="viewport" content="width=device-width, initial-scale=1.0">
367367 <title>Unified Graph Analysis Report</title>
368368 <link rel="stylesheet" href="style.css">
369+ <script src="https://cdn.plot.ly/plotly-2.26.0.min.js"></script>
369370</head>
370371<body>
371372 <div class="container">
@@ -389,6 +390,7 @@ def write_html_report(
389390 <div id="summary" class="tab-pane active">
390391 <h2>Summary</h2>
391392 <p class="explanation">These are high-level counts of nodes/edges for each graph constructed during analysis.</p>
393+ <div id="summary-chart"></div>
392394 <ul class="summary-list">
393395""" )
394396 for k , v in summary .items ():
@@ -403,6 +405,7 @@ def write_html_report(
403405
404406 <h3>Top Nodes by Degree</h3>
405407 <p class="explanation">These are the people connected to the most unique others across meetings.</p>
408+ <div id="coattendance-top-chart"></div>
406409 <table>
407410 <thead>
408411 <tr><th>Rank</th><th>Node</th><th>Degree</th></tr>
@@ -417,6 +420,7 @@ def write_html_report(
417420
418421 <h3>Degree Distribution</h3>
419422 <p class="explanation">How many people fall into each degree (number of unique co-attendees) bucket.</p>
423+ <div id="coattendance-dist-chart"></div>
420424 <table>
421425 <thead>
422426 <tr><th>Degree</th><th>Count of Nodes</th></tr>
@@ -436,6 +440,7 @@ def write_html_report(
436440
437441 <h3>Top Fields by Degree</h3>
438442 <p class="explanation">These fields co-occur with the largest variety of other fields.</p>
443+ <div id="field-degree-top-chart"></div>
439444 <table>
440445 <thead>
441446 <tr><th>Rank</th><th>Field</th><th>Degree</th></tr>
@@ -450,6 +455,7 @@ def write_html_report(
450455
451456 <h3>Degree Distribution</h3>
452457 <p class="explanation">How many fields have each degree (number of distinct co-occurring fields).</p>
458+ <div id="field-degree-dist-chart"></div>
453459 <table>
454460 <thead>
455461 <tr><th>Degree</th><th>Count of Fields</th></tr>
@@ -483,6 +489,7 @@ def write_html_report(
483489
484490 <h3>Most Common Parent Paths</h3>
485491 <p class="explanation">Parents that appear most often, suggesting common structural hubs.</p>
492+ <div id="path-structure-chart"></div>
486493 <table>
487494 <thead>
488495 <tr><th>Rank</th><th>Parent Path</th><th>Count</th></tr>
@@ -500,6 +507,7 @@ def write_html_report(
500507 <h2>Field Centrality (Co-occurrence)</h2>
501508 <p class="explanation">Centrality scores highlight fields that are well-connected (degree), act as bridges (betweenness), are close to others (closeness), or connect to other influential fields (eigenvector).</p>
502509
510+ <div id="centrality-chart"></div>
503511 <table>
504512 <thead>
505513 <tr><th>Rank</th><th>Field</th><th>Degree</th><th>Betweenness</th><th>Closeness</th><th>Eigenvector</th></tr>
@@ -532,6 +540,7 @@ def write_html_report(
532540
533541 <h3>Top Nodes by Clustering Coefficient</h3>
534542 <p class="explanation">Fields whose immediate neighborhoods are most tightly interlinked.</p>
543+ <div id="clustering-chart"></div>
535544 <table>
536545 <thead>
537546 <tr><th>Rank</th><th>Field</th><th>Clustering</th></tr>
@@ -549,6 +558,7 @@ def write_html_report(
549558 <h2>Connected Components (Field Co-occurrence Graph)</h2>
550559 <p class="explanation">Components are groups of fields that are all reachable from each other; multiple components suggest separate substructures.</p>
551560
561+ <div id="components-chart"></div>
552562 <ul class="summary-list">
553563 <li><strong>Number of Components:</strong> """ + str (components ['component_count' ]) + """</li>
554564 <li><strong>Component Sizes (top 10):</strong> """ + str (components ['component_sizes' ][:10 ]) + """</li>
@@ -564,6 +574,29 @@ def write_html_report(
564574 </div>
565575 </div>
566576
577+ <script type="text/javascript">
578+ // Embedded chart data
579+ const chartData = {
580+ summary: """ + json .dumps ({k : v for k , v in summary .items ()}) + """,
581+ coattendanceTop: """ + json .dumps ([{"node" : _truncate_label (node , 80 ), "degree" : deg } for node , deg in attend_top ], ensure_ascii = False ) + """,
582+ coattendanceDist: """ + json .dumps ([{"degree" : d , "count" : c } for d , c in attend_dist ]) + """,
583+ fieldDegreeTop: """ + json .dumps ([{"field" : _truncate_label (node , 80 ), "degree" : deg } for node , deg in field_top ], ensure_ascii = False ) + """,
584+ fieldDegreeDist: """ + json .dumps ([{"degree" : d , "count" : c } for d , c in field_dist ]) + """,
585+ pathStructure: """ + json .dumps ([{"parent" : parent , "count" : cnt } for parent , cnt in parent_top ], ensure_ascii = False ) + """,
586+ centrality: """ + json .dumps ([{
587+ "field" : node ,
588+ "degree" : round (centrality ["degree" ].get (node , 0 ), 3 ),
589+ "betweenness" : round (centrality ["betweenness" ].get (node , 0 ), 3 ),
590+ "closeness" : round (centrality ["closeness" ].get (node , 0 ), 3 ),
591+ "eigenvector" : round (centrality ["eigenvector" ].get (node , 0 ), 3 )
592+ } for node in sorted (centrality ["degree" ].keys (), key = lambda x : centrality ["degree" ][x ], reverse = True )[:10 ]], ensure_ascii = False ) + """,
593+ clustering: """ + json .dumps ([{"field" : node , "clustering" : round (val , 3 )} for node , val in top_clust_nodes ], ensure_ascii = False ) + """,
594+ components: """ + json .dumps ({
595+ "count" : components ['component_count' ],
596+ "sizes" : components ['component_sizes' ][:10 ]
597+ }) + """
598+ };
599+ </script>
567600 <script src="script.js"></script>
568601</body>
569602</html>
0 commit comments