Claude Claude commited on
Commit
e7dd723
·
unverified ·
1 Parent(s): b85786b

Fix population network distribution and add opinion-based node coloring

Browse files

Fixes:
1. Population Network: Fixed persona distribution to use all selected personas
- Added check to skip personas with zero weight
- Now correctly distributes 30 nodes across 4 selected personas
- Previously only used 1 persona and created 8 nodes

2. Network Visualization: Added opinion-based node coloring
- Nodes now colored by final opinion position:
* Dark green = Strongly Support
* Green = Support
* Light green = Lean Support
* Gray = Neutral
* Light red = Lean Oppose
* Red = Oppose
* Dark red = Strongly Oppose
- Added opinion position to hover text
- Removed centrality-based coloring

3. Note: Sidebar still shows 'Web App' - pages.toml not fully supported yet

Files modified:
- src/influence/population_network.py: Fixed weight-based distribution
- pages/3_🌐_Opinion_Equilibria.py: Added opinion color scheme

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

pages/3_🌐_Opinion_Equilibria.py CHANGED
@@ -566,22 +566,44 @@ if st.session_state.equilibrium_results:
566
  )
567
  )
568
 
569
- # Node trace
570
  node_x = []
571
  node_y = []
572
  node_text = []
573
  node_color = []
574
 
575
- network_metrics = influence_network.calculate_network_metrics()
576
- centrality = network_metrics.centrality_scores
 
 
 
 
 
 
 
 
 
 
 
577
 
578
  for node in G.nodes():
579
  x, y = pos[node]
580
  node_x.append(x)
581
  node_y.append(y)
582
  node_data = G.nodes[node]
583
- node_text.append(f"{node_data['label']}<br>{node_data['role']}")
584
- node_color.append(centrality.get(node, 0))
 
 
 
 
 
 
 
 
 
 
 
585
 
586
  node_trace = go.Scatter(
587
  x=node_x,
@@ -593,10 +615,7 @@ if st.session_state.equilibrium_results:
593
  marker=dict(
594
  size=20,
595
  color=node_color,
596
- colorscale="Viridis",
597
- showscale=True,
598
- colorbar=dict(title="Influence<br>Centrality"),
599
- line=dict(width=2, color="white"),
600
  ),
601
  showlegend=False,
602
  )
 
566
  )
567
  )
568
 
569
+ # Node trace - color by opinion position
570
  node_x = []
571
  node_y = []
572
  node_text = []
573
  node_color = []
574
 
575
+ # Map persona_id to final opinion
576
+ opinion_map = {op.persona_id: op for op in equilibrium.final_opinions}
577
+
578
+ # Define color scheme for opinions
579
+ opinion_colors = {
580
+ "strongly_support": "#2E7D32", # Dark green
581
+ "support": "#66BB6A", # Green
582
+ "lean_support": "#A5D6A7", # Light green
583
+ "neutral": "#BDBDBD", # Gray
584
+ "lean_oppose": "#EF9A9A", # Light red
585
+ "oppose": "#E57373", # Red
586
+ "strongly_oppose": "#C62828", # Dark red
587
+ }
588
 
589
  for node in G.nodes():
590
  x, y = pos[node]
591
  node_x.append(x)
592
  node_y.append(y)
593
  node_data = G.nodes[node]
594
+
595
+ # Get opinion for this node
596
+ opinion = opinion_map.get(node_data.get('persona_id', node))
597
+ if opinion:
598
+ position_str = opinion.position.value
599
+ color = opinion_colors.get(position_str, "#BDBDBD")
600
+ position_label = position_str.replace("_", " ").title()
601
+ node_text.append(f"{node_data['label']}<br>{node_data['role']}<br>Opinion: {position_label}")
602
+ else:
603
+ color = "#BDBDBD"
604
+ node_text.append(f"{node_data['label']}<br>{node_data['role']}")
605
+
606
+ node_color.append(color)
607
 
608
  node_trace = go.Scatter(
609
  x=node_x,
 
615
  marker=dict(
616
  size=20,
617
  color=node_color,
618
+ line=dict(width=2, color="DarkSlateGrey"),
 
 
 
619
  ),
620
  showlegend=False,
621
  )
src/influence/population_network.py CHANGED
@@ -72,7 +72,12 @@ class PopulationNetwork:
72
  # Use custom weights to distribute population
73
  for base_persona in self.base_personas:
74
  weight = self.persona_weights.get(base_persona.persona_id, 0)
 
 
 
75
  count = int(round(weight * self.population_size))
 
 
76
 
77
  generator = VariantGenerator(base_persona, self.variation_level)
78
  persona_variants = [
 
72
  # Use custom weights to distribute population
73
  for base_persona in self.base_personas:
74
  weight = self.persona_weights.get(base_persona.persona_id, 0)
75
+ if weight == 0:
76
+ continue # Skip personas with zero weight
77
+
78
  count = int(round(weight * self.population_size))
79
+ if count == 0:
80
+ continue # Skip if rounding resulted in zero
81
 
82
  generator = VariantGenerator(base_persona, self.variation_level)
83
  persona_variants = [