Models Package

The models package provides core data structures and the main database interface for working with YSocial simulation data.

YDataHandler

The main interface for database operations and data retrieval.

class ysights.models.YDataHandler.UserPost(agent_id, post_id)

Bases: tuple

agent_id

Alias for field number 0

post_id

Alias for field number 1

class ysights.models.YDataHandler.YDataHandler(db_path)[source]

Bases: object

Main handler for YSocial simulation database operations.

This class provides a comprehensive interface for querying and analyzing data from YSocial simulations. It manages database connections, retrieves agent and post information, extracts social networks, and provides various analytical methods for understanding simulation dynamics.

Supports both SQLite and PostgreSQL databases with the same table structure.

Parameters:

db_path (str) – Path to SQLite database file or PostgreSQL connection string

Variables:
  • db_path (str) – Database path or connection string

  • db_type (str) – Type of database (‘sqlite’ or ‘postgresql’)

  • connection – Active database connection (None when not connected)

Example

Basic usage with SQLite:

from ysights import YDataHandler

# Initialize handler with SQLite database
ydh = YDataHandler('path/to/simulation_data.db')

# Get time range of simulation
time_info = ydh.time_range()
print(f"Simulation runs from round {time_info['min_round']} to {time_info['max_round']}")

# Get all agents
agents = ydh.agents()
print(f"Total agents: {len(agents.get_agents())}")

Basic usage with PostgreSQL:

from ysights import YDataHandler

# Initialize handler with PostgreSQL database
ydh = YDataHandler('postgresql://user:password@localhost:5432/ysocial_db')

# Use the same methods as with SQLite
agents = ydh.agents()
print(f"Total agents: {len(agents.get_agents())}")

# Get posts by specific agent with enriched data
agent_posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['sentiment', 'hashtags'])
for post in agent_posts.get_posts():
    print(f"Post: {post.text}")
    print(f"Sentiment: {post.sentiment}")

# Extract social network
network = ydh.social_network(from_round=0, to_round=100)
print(f"Network has {network.number_of_nodes()} nodes and {network.number_of_edges()} edges")

Note

Database connections are automatically managed through the internal decorator _handle_db_connection. Methods that query the database will automatically open and close connections as needed.

See also

ysights.models.Agents.Agents: Container for agent collections ysights.models.Posts.Posts: Container for post collections

__init__(db_path)[source]

Initialize the YDataHandler with database connection information.

Parameters:

db_path (str) –

Path to SQLite database file or PostgreSQL connection string. For SQLite: ‘path/to/database.db’ For PostgreSQL: ‘postgresql://user:password@host:port/database’

or ‘postgres://user:password@host:port/database’

Raises:
  • FileNotFoundError – If the SQLite database file does not exist when first accessed

  • ImportError – If PostgreSQL connection string is used but psycopg2 is not installed

Example:

# SQLite
ydh = YDataHandler('simulation_results/data.db')

# PostgreSQL
ydh = YDataHandler('postgresql://user:password@localhost:5432/ysocial_db')
wraps(assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotations__', '__type_params__'), updated=('__dict__',))

Decorator factory to apply update_wrapper() to a wrapper function

Returns a decorator that invokes update_wrapper() with the decorated function as the wrapper argument and the arguments to wraps() as the remaining arguments. Default arguments are as for update_wrapper(). This is a convenience function to simplify applying partial() to update_wrapper().

custom_query(query)[source]

Execute a custom SQL query and return the results.

This method allows execution of arbitrary SQL queries against the database. Use with caution and ensure proper SQL injection protection for user inputs.

Parameters:

query (str) – SQL query string to execute

Returns:

Query results as list of tuples

Return type:

list

Example:

ydh = YDataHandler('path/to/database.db')

# Execute custom query
results = ydh.custom_query("SELECT COUNT(*) FROM post WHERE round < 100")
print(f"Posts in first 100 rounds: {results[0][0]}")

# More complex query
query = '''
    SELECT u.username, COUNT(p.id) as post_count
    FROM user_mgmt u
    JOIN post p ON u.id = p.user_id
    GROUP BY u.id
    ORDER BY post_count DESC
    LIMIT 10
'''
top_posters = ydh.custom_query(query)
for username, count in top_posters:
    print(f"{username}: {count} posts")

Warning

Be careful with user-provided input to avoid SQL injection vulnerabilities. Consider using parameterized queries when possible.

time_range()[source]

Retrieve the time range covered by the simulation.

Returns the minimum and maximum round IDs present in the database, representing the temporal extent of the simulation data.

Returns:

Dictionary with ‘min_round’ and ‘max_round’ keys

Return type:

dict

Raises:

ValueError – If no rounds are found in the database

Example:

ydh = YDataHandler('path/to/database.db')

time_info = ydh.time_range()
print(f"Simulation starts at round: {time_info['min_round']}")
print(f"Simulation ends at round: {time_info['max_round']}")
print(f"Total rounds: {time_info['max_round'] - time_info['min_round'] + 1}")
round_to_time(round_id)[source]

Convert a round ID to its corresponding day and hour representation.

Parameters:

round_id (int) – The round ID to convert

Returns:

Dictionary with ‘day’ and ‘hour’ keys

Return type:

dict

Raises:

ValueError – If the round ID does not exist in the database

Example:

ydh = YDataHandler('path/to/database.db')

time_info = ydh.round_to_time(round_id=250)
print(f"Round 250 occurred on day {time_info['day']} at hour {time_info['hour']}")

# Converting multiple rounds
for round_id in [100, 200, 300]:
    time = ydh.round_to_time(round_id)
    print(f"Round {round_id}: Day {time['day']}, Hour {time['hour']}")
time_to_round(day, hour=0)[source]

Convert a day and hour to the corresponding round ID.

Parameters:
  • day (int) – The simulation day

  • hour (int) – The hour within the day (default: 0)

Returns:

The round ID corresponding to the specified time

Return type:

int

Raises:

ValueError – If no round exists for the specified day and hour

Example:

ydh = YDataHandler('path/to/database.db')

# Get round ID for day 10, hour 5
round_id = ydh.time_to_round(day=10, hour=5)
print(f"Day 10, Hour 5 is round {round_id}")

# Get round ID for start of day 5
round_id = ydh.time_to_round(day=5)
print(f"Day 5 starts at round {round_id}")
number_of_agents()[source]

Get the total number of agents in the simulation.

Returns:

Total count of agents

Return type:

int

Example:

ydh = YDataHandler('path/to/database.db')

agent_count = ydh.number_of_agents()
print(f"Total agents in simulation: {agent_count}")
agents()[source]

Retrieve all agents from the simulation database.

Returns an Agents collection containing all agent records with their complete demographic and behavioral attributes.

Returns:

Collection of all agents

Return type:

Agents

Example:

ydh = YDataHandler('path/to/database.db')

agents = ydh.agents()
print(f"Total agents: {len(agents.get_agents())}")

# Analyze agent demographics
for agent in agents.get_agents():
    print(f"Agent {agent.id}: {agent.username}")
    print(f"  Age: {agent.age}, Gender: {agent.gender}")
    print(f"  Leaning: {agent.leaning}")
    print(f"  Personality: {agent.personality}")

See also

agents_by_feature(): Filter agents by specific attributes ysights.models.Agents.Agents: Agents collection class

agents_by_feature(feature, value)[source]

Retrieve agents filtered by a specific feature value.

Allows querying agents based on any column in the user_mgmt table, such as leaning, gender, role, education, etc.

Parameters:
  • feature (str) – The column name to filter by (e.g., ‘leaning’, ‘gender’, ‘role’)

  • value (str or int) – The value to match for the specified feature

Returns:

Collection of matching agents

Return type:

Agents

Example:

ydh = YDataHandler('path/to/database.db')

# Get all agents with left-leaning political orientation
left_agents = ydh.agents_by_feature('leaning', 'left')
print(f"Left-leaning agents: {len(left_agents.get_agents())}")

# Get all female agents
female_agents = ydh.agents_by_feature('gender', 'female')

# Get all agents with college education
college_agents = ydh.agents_by_feature('education', 'college')

for agent in college_agents.get_agents():
    print(f"{agent.username} - {agent.profession}")

Warning

The feature parameter is directly inserted into SQL query. Ensure it comes from trusted sources to prevent SQL injection.

See also

agents(): Get all agents without filtering

agent_mapping()[source]

Get a mapping of agent IDs to usernames.

Provides a convenient dictionary for looking up agent usernames by their IDs.

Returns:

Dictionary mapping agent IDs to usernames

Return type:

dict

Example:

ydh = YDataHandler('path/to/database.db')

mapping = ydh.agent_mapping()
print(f"Agent 5's username: {mapping[5]}")

# Use mapping to display usernames in analysis
post_counts = {}  # hypothetical post count data
for agent_id, count in post_counts.items():
    username = mapping.get(agent_id, 'Unknown')
    print(f"{username}: {count} posts")
agent_post_ids(agent_id)[source]

Get all post IDs created by a specific agent.

Parameters:

agent_id (int) – The ID of the agent

Returns:

Dictionary of post IDs (post_id -> post_id mapping)

Return type:

dict

Example:

ydh = YDataHandler('path/to/database.db')

post_ids = ydh.agent_post_ids(agent_id=5)
print(f"Agent 5 created {len(post_ids)} posts")
print(f"Post IDs: {list(post_ids.keys())}")

See also

posts_by_agent(): Get full Post objects instead of just IDs

posts()[source]

Retrieve all posts from the simulation database.

Returns a Posts collection containing all post records without enrichment. For enriched posts with sentiment, hashtags, etc., use posts_by_agent() with enrich_dimensions parameter.

Returns:

Collection of all posts

Return type:

Posts

Example:

ydh = YDataHandler('path/to/database.db')

posts = ydh.posts()
print(f"Total posts in simulation: {len(posts.get_posts())}")

# Analyze post distribution
rounds = [post.round for post in posts.get_posts()]
print(f"Posts range from round {min(rounds)} to {max(rounds)}")

See also

posts_by_agent(): Get posts by specific agent with enrichment options ysights.models.Posts.Posts: Posts collection class

posts_by_agent(agent_id, enrich_dimensions=['all'])[source]

Retrieve posts created by a specific agent with optional enrichment.

This method allows selective enrichment of posts with additional data such as sentiment scores, hashtags, topics, mentions, emotions, toxicity, and reactions. Use specific dimensions for faster queries or ‘all’ for complete enrichment.

Parameters:
  • agent_id (int) – The ID of the agent whose posts to retrieve

  • enrich_dimensions (list[str]) – List of dimensions to enrich. Options: ‘sentiment’, ‘hashtags’, ‘mentions’, ‘emotions’, ‘topics’, ‘toxicity’, ‘reactions’, ‘all’, or []

Returns:

Collection of posts by the specified agent

Return type:

Posts

Example:

ydh = YDataHandler('path/to/database.db')

# Get posts with full enrichment
posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['all'])
for post in posts.get_posts():
    print(f"Post: {post.text}")
    print(f"Sentiment: {post.sentiment}")
    print(f"Hashtags: {post.hashtags}")
    print(f"Topics: {post.topics}")

# Get posts with selective enrichment (faster)
posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['sentiment', 'hashtags'])

# Get posts without enrichment
posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=[])

See also

Post.enrich_post(): Method that performs the enrichment posts(): Get all posts without filtering

agent_id_by_post_id(post_id)[source]

Get the agent ID who created a specific post.

Parameters:

post_id (int) – The ID of the post

Returns:

The ID of the agent who created the post

Return type:

int

Raises:

ValueError – If the post ID does not exist in the database

Example:

ydh = YDataHandler('path/to/database.db')

agent_id = ydh.agent_id_by_post_id(post_id=123)
print(f"Post 123 was created by agent {agent_id}")

# Get username of post author
mapping = ydh.agent_mapping()
username = mapping[agent_id]
print(f"Author: {username}")
agent_recommendations(agent_id, from_round=None, to_round=None)[source]

Get recommendations received by a specific agent.

Returns the posts recommended to an agent, optionally filtered by time range. Each post is represented as a UserPost namedtuple containing the post author’s ID and the post ID, with a count of how many times it was recommended.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping UserPost to recommendation count

Return type:

dict[UserPost, int]

Example:

ydh = YDataHandler('path/to/database.db')

# Get all recommendations for agent 5
recs = ydh.agent_recommendations(agent_id=5)
print(f"Agent 5 received {len(recs)} unique post recommendations")

for user_post, count in recs.items():
    print(f"Post {user_post.post_id} by agent {user_post.agent_id}: {count} times")

# Get recommendations in specific time range
recs = ydh.agent_recommendations(agent_id=5, from_round=100, to_round=200)
print(f"Recommendations in rounds 100-200: {len(recs)}")

See also

recommendations_per_post(): Get recommendation counts per post agent_posts_visibility(): Get visibility of agent’s own posts

agent_posts_visibility(agent_id, rec_stats, from_round=None, to_round=None)[source]

Get visibility metrics for posts created by a specific agent.

Calculates how many times each of the agent’s posts was recommended to others. This provides insight into the reach and visibility of an agent’s content.

Parameters:
  • agent_id (int) – The ID of the agent whose posts to analyze

  • rec_stats (dict[int, int]) – Dictionary of post IDs to their recommendation counts (typically from recommendations_per_post())

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping post IDs to recommendation counts

Return type:

dict[int, int]

Example:

ydh = YDataHandler('path/to/database.db')

# First get overall recommendation stats
rec_stats = ydh.recommendations_per_post()

# Then get visibility for specific agent
visibility = ydh.agent_posts_visibility(agent_id=5, rec_stats=rec_stats)
print(f"Agent 5's post visibility:")
for post_id, count in visibility.items():
    print(f"  Post {post_id} was recommended {count} times")

# Get visibility in specific time range
visibility = ydh.agent_posts_visibility(
    agent_id=5, rec_stats=rec_stats,
    from_round=100, to_round=200
)

See also

recommendations_per_post(): Get recommendation statistics agent_recommendations(): Get recommendations received by agent

recommendations_per_post()[source]

Get recommendation counts for all posts in the simulation.

Aggregates how many times each post was recommended across all agents and all rounds. Useful for identifying popular or viral content.

Returns:

Dictionary mapping post IDs to their total recommendation counts

Return type:

dict[int, int]

Example:

ydh = YDataHandler('path/to/database.db')

rec_stats = ydh.recommendations_per_post()

# Find most recommended posts
sorted_posts = sorted(rec_stats.items(), key=lambda x: x[1], reverse=True)
print("Top 10 most recommended posts:")
for post_id, count in sorted_posts[:10]:
    print(f"  Post {post_id}: {count} recommendations")

# Use for visibility analysis
visibility = ydh.agent_posts_visibility(agent_id=5, rec_stats=rec_stats)

See also

recommendations_per_post_per_user(): Get per-user recommendation data agent_posts_visibility(): Use stats for visibility analysis

recommendations_per_post_per_user()[source]

Get detailed recommendation data including per-user reading history.

Returns both aggregated recommendation counts per post and a mapping of which posts each user received in their recommendations. This provides detailed insight into content distribution patterns.

Returns:

Tuple of (post_recs, user_to_posts_read) where: - post_recs: dict mapping post_id to recommendation count - user_to_posts_read: dict mapping user_id to list of post_ids they received

Return type:

tuple[dict[int, int], dict[int, list[int]]]

Example:

ydh = YDataHandler('path/to/database.db')

post_recs, user_reading_history = ydh.recommendations_per_post_per_user()

# Analyze post popularity
print("Most recommended posts:")
for post_id, count in sorted(post_recs.items(), key=lambda x: x[1], reverse=True)[:5]:
    print(f"  Post {post_id}: {count} recommendations")

# Analyze user reading patterns
user_id = 5
posts_seen = user_reading_history[user_id]
print(f"Agent {user_id} saw {len(posts_seen)} posts")
print(f"Average recommendations per post: {sum(post_recs.values()) / len(post_recs):.2f}")

See also

recommendations_per_post(): Simpler version with just post counts agent_recommendations(): Get recommendations for specific agent

agent_reactions(agent_id, from_round=None, to_round=None)[source]

Get all reactions made by a specific agent.

Returns reactions (likes, loves, etc.) that an agent has given to posts, optionally filtered by time range. Results are grouped by reaction type.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping reaction types to lists of post IDs

Return type:

dict[str, list[int]]

Example:

ydh = YDataHandler('path/to/database.db')

reactions = ydh.agent_reactions(agent_id=5)
print(f"Agent 5's reactions:")
for reaction_type, post_ids in reactions.items():
    print(f"  {reaction_type}: {len(post_ids)} posts")

# Reactions in specific time range
reactions = ydh.agent_reactions(agent_id=5, from_round=100, to_round=200)
like_count = len(reactions.get('like', []))
print(f"Likes in rounds 100-200: {like_count}")

See also

agent_hashtags(): Get hashtags used by agent agent_interests(): Get interests of agent

agent_hashtags(agent_id, from_round=None, to_round=None)[source]

Get hashtags used by a specific agent in their posts.

Returns all hashtags the agent has used, with counts indicating frequency of use. Optionally filter by time range.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping hashtags to their usage counts

Return type:

dict[str, int]

Example:

ydh = YDataHandler('path/to/database.db')

hashtags = ydh.agent_hashtags(agent_id=5)
print("Agent 5's most used hashtags:")
for tag, count in sorted(hashtags.items(), key=lambda x: x[1], reverse=True)[:10]:
    print(f"  #{tag}: {count} times")

# Hashtags in specific period
recent_tags = ydh.agent_hashtags(agent_id=5, from_round=500, to_round=1000)
print(f"Used {len(recent_tags)} different hashtags in rounds 500-1000")

See also

agent_interests(): Get interests of agent agent_topics(): Get topics agent engages with

agent_interests(agent_id, from_round=None, to_round=None)[source]

Get the interest profile of a specific agent.

Returns the interests/topics that the agent is associated with, including counts indicating strength or frequency of each interest. Optionally filter by time range.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping interests to their frequency counts

Return type:

dict[str, int]

Example:

ydh = YDataHandler('path/to/database.db')

interests = ydh.agent_interests(agent_id=5)
print("Agent 5's interest profile:")
for interest, count in sorted(interests.items(), key=lambda x: x[1], reverse=True):
    print(f"  {interest}: {count}")

# Track interest evolution
early_interests = ydh.agent_interests(agent_id=5, from_round=0, to_round=500)
late_interests = ydh.agent_interests(agent_id=5, from_round=500, to_round=1000)

new_interests = set(late_interests.keys()) - set(early_interests.keys())
print(f"New interests acquired: {new_interests}")

See also

agent_hashtags(): Get hashtags used by agent agent_emotions(): Get emotional profile of agent

agent_emotions(agent_id, from_round=None, to_round=None)[source]

Get the emotional profile of a specific agent’s posts.

Returns emotions detected in the agent’s posts, with counts indicating how frequently each emotion appears. Optionally filter by time range.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Dictionary mapping emotions to their frequency counts

Return type:

dict[str, int]

Example:

ydh = YDataHandler('path/to/database.db')

emotions = ydh.agent_emotions(agent_id=5)
print("Agent 5's emotional expression:")
for emotion, count in sorted(emotions.items(), key=lambda x: x[1], reverse=True):
    print(f"  {emotion}: {count} posts")

# Compare emotional states over time
early_emotions = ydh.agent_emotions(agent_id=5, from_round=0, to_round=500)
late_emotions = ydh.agent_emotions(agent_id=5, from_round=500, to_round=1000)

joy_change = late_emotions.get('joy', 0) - early_emotions.get('joy', 0)
print(f"Change in joy expression: {joy_change}")

See also

agent_toxicity(): Get toxicity profile agent_interests(): Get interest profile

agent_toxicity(agent_id, from_round=None, to_round=None)[source]

Get the toxicity profile of a specific agent’s posts.

Returns detailed toxicity scores for each of the agent’s posts, including overall toxicity and specific toxic dimensions (severe toxicity, identity attacks, insults, profanity, threats, sexual content, flirtation). Optionally filter by time range.

Parameters:
  • agent_id (int) – The ID of the agent

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

List of dictionaries, each containing toxicity scores for a post

Return type:

list[dict]

Example:

ydh = YDataHandler('path/to/database.db')

toxicity_data = ydh.agent_toxicity(agent_id=5)
print(f"Agent 5 toxicity analysis over {len(toxicity_data)} posts:")

# Calculate average toxicity
if toxicity_data:
    avg_tox = sum(p['toxicity'] for p in toxicity_data) / len(toxicity_data)
    print(f"Average toxicity: {avg_tox:.3f}")

    # Check for specific toxic behaviors
    high_profanity = [p for p in toxicity_data if p['profanity'] > 0.7]
    print(f"Posts with high profanity: {len(high_profanity)}")

# Compare toxicity over time periods
early_tox = ydh.agent_toxicity(agent_id=5, from_round=0, to_round=500)
late_tox = ydh.agent_toxicity(agent_id=5, from_round=500, to_round=1000)

Note

Toxicity scores are typically in the range [0, 1] where higher values indicate more toxic content.

See also

agent_emotions(): Get emotional profile posts_by_agent(): Get full post objects with toxicity data

ego_network_follower(agent_id, from_round=None, to_round=None)[source]

Extract the follower ego network for a specific agent.

Returns a directed network showing agents who follow the specified agent. The network accounts for follow/unfollow dynamics, keeping only active connections at the end of the time period.

Parameters:
  • agent_id (int) – The ID of the agent (the “ego”)

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Directed graph with edges pointing from ego to followers

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Get follower network for agent 5
follower_net = ydh.ego_network_follower(agent_id=5)
print(f"Agent 5 has {follower_net.number_of_nodes() - 1} followers")
print(f"Follower IDs: {list(follower_net.successors(5))}")

# Get follower network in specific time period
recent_followers = ydh.ego_network_follower(agent_id=5, from_round=500, to_round=1000)

Note

This method tracks follow/unfollow actions. If an edge has been followed and then unfollowed (even number of actions), it is removed from the final network.

See also

ego_network_following(): Get accounts the agent follows ego_network(): Get complete ego network (both followers and following)

ego_network_following(agent_id, from_round=None, to_round=None)[source]

Extract the following ego network for a specific agent.

Returns a directed network showing agents that the specified agent follows. The network accounts for follow/unfollow dynamics, keeping only active connections at the end of the time period.

Parameters:
  • agent_id (int) – The ID of the agent (the “ego”)

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Directed graph with edges pointing from accounts followed to ego

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Get following network for agent 5
following_net = ydh.ego_network_following(agent_id=5)
print(f"Agent 5 follows {following_net.number_of_nodes() - 1} accounts")
print(f"Following IDs: {list(following_net.predecessors(5))}")

# Compare early vs late following behavior
early = ydh.ego_network_following(agent_id=5, from_round=0, to_round=500)
late = ydh.ego_network_following(agent_id=5, from_round=500, to_round=1000)
print(f"Early following count: {early.number_of_nodes() - 1}")
print(f"Late following count: {late.number_of_nodes() - 1}")

Note

This method tracks follow/unfollow actions. If an edge has been followed and then unfollowed (even number of actions), it is removed from the final network.

See also

ego_network_follower(): Get followers of the agent ego_network(): Get complete ego network (both followers and following)

ego_network(agent_id, from_round=None, to_round=None)[source]

Extract the complete ego network for a specific agent.

Returns a directed network combining both followers (who follow the agent) and following (accounts the agent follows). This provides a comprehensive view of the agent’s social connections.

Parameters:
  • agent_id (int) – The ID of the agent (the “ego”)

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Directed graph representing the complete ego network

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Get complete ego network for agent 5
ego_net = ydh.ego_network(agent_id=5)
print(f"Agent 5's ego network has {ego_net.number_of_nodes()} nodes")
print(f"Edges: {ego_net.number_of_edges()}")

# Analyze network structure
in_degree = ego_net.in_degree(5)  # Number of followers
out_degree = ego_net.out_degree(5)  # Number following
print(f"Followers: {in_degree}, Following: {out_degree}")

# Get ego network for specific time period
period_net = ydh.ego_network(agent_id=5, from_round=100, to_round=500)

See also

ego_network_follower(): Get only follower connections ego_network_following(): Get only following connections social_network(): Get complete social network for all agents

social_network(from_round=None, to_round=None, agent_ids=None)[source]

Extract the complete social network from the simulation.

Builds a directed graph representing the follow relationships between all agents (or a specified subset). Each agent’s ego network is extracted and then merged into a single comprehensive social network.

Parameters:
  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

  • agent_ids (list[int], optional) – List of agent IDs to include. If None, all agents are included

Returns:

Directed graph representing the complete social network

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler
import matplotlib.pyplot as plt

ydh = YDataHandler('path/to/database.db')

# Get complete social network
social_net = ydh.social_network()
print(f"Social network: {social_net.number_of_nodes()} nodes, {social_net.number_of_edges()} edges")

# Analyze network properties
density = nx.density(social_net)
print(f"Network density: {density:.4f}")

# Get network for specific agents
agent_subset = [1, 2, 3, 5, 8, 13, 21]
subnet = ydh.social_network(agent_ids=agent_subset)

# Get network for specific time period
early_net = ydh.social_network(from_round=0, to_round=500)
late_net = ydh.social_network(from_round=500, to_round=1000)

# Compare network evolution
print(f"Early network: {early_net.number_of_edges()} edges")
print(f"Late network: {late_net.number_of_edges()} edges")

Warning

Extracting the complete social network for all agents can be slow for large simulations. Consider using the agent_ids parameter to limit the scope or using time range filtering.

See also

ego_network(): Get ego network for single agent mention_network(): Get mention-based interaction network

mention_ego_network(agent_id, from_round=None, to_round=None)[source]

Extract the mention ego network for a specific agent.

Returns a directed weighted network showing which agents the specified agent has mentioned in their posts. Edge weights represent the number of times each agent was mentioned.

Parameters:
  • agent_id (int) – The ID of the agent (the “ego”)

  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

Returns:

Directed weighted graph with edges from ego to mentioned agents

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Get mention network for agent 5
mention_net = ydh.mention_ego_network(agent_id=5)
print(f"Agent 5 has mentioned {mention_net.number_of_nodes() - 1} different agents")

# Analyze mention patterns
for target in mention_net.successors(5):
    weight = mention_net[5][target]['weight']
    print(f"  Mentioned agent {target}: {weight} times")

# Compare mention patterns over time
early_mentions = ydh.mention_ego_network(agent_id=5, from_round=0, to_round=500)
late_mentions = ydh.mention_ego_network(agent_id=5, from_round=500, to_round=1000)

See also

mention_network(): Get complete mention network for all agents ego_network(): Get follower/following network

mention_network(from_round=None, to_round=None, agent_ids=None)[source]

Extract the complete mention network from the simulation.

Builds a directed weighted graph representing mention relationships between all agents (or a specified subset). Edges indicate one agent mentioning another in their posts, with weights showing mention frequency.

Parameters:
  • from_round (int, optional) – Starting round for filtering (inclusive), None for no lower bound

  • to_round (int, optional) – Ending round for filtering (inclusive), None for no upper bound

  • agent_ids (list[int], optional) – List of agent IDs to include. If None, all agents are included

Returns:

Directed weighted graph representing the mention network

Return type:

networkx.DiGraph

Example:

import networkx as nx
from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Get complete mention network
mention_net = ydh.mention_network()
print(f"Mention network: {mention_net.number_of_nodes()} nodes, {mention_net.number_of_edges()} edges")

# Find most mentioned agents
in_degrees = dict(mention_net.in_degree(weight='weight'))
top_mentioned = sorted(in_degrees.items(), key=lambda x: x[1], reverse=True)[:5]
print("Most mentioned agents:")
for agent_id, mention_count in top_mentioned:
    print(f"  Agent {agent_id}: mentioned {mention_count} times")

# Get mention network for subset
agent_subset = [1, 2, 3, 5, 8]
subnet = ydh.mention_network(agent_ids=agent_subset)

# Compare mention patterns over time
early = ydh.mention_network(from_round=0, to_round=500)
late = ydh.mention_network(from_round=500, to_round=1000)

Warning

Extracting the complete mention network for all agents can be slow for large simulations. Consider using the agent_ids parameter or time range filtering.

See also

mention_ego_network(): Get mention network for single agent social_network(): Get follower/following network

Agent Classes

Classes for representing individual agents and agent collections.

class ysights.models.Agents.Agent(row)[source]

Bases: object

Represents a social media agent in the YSocial simulation.

This class encapsulates all properties and characteristics of an agent, including demographic information, personality traits, recommendation system preferences, and behavioral attributes.

Parameters:

row (tuple) – A database row tuple containing agent data in a specific order: [id, username, ?, ?, role, leaning, age, oe, co, ex, ag, ne, content_recsys, language, ?, education, joined, social_recsys, gender, nationality, toxicity, is_page, left_on, daily_activity_level, profession]

Variables:
  • id (int) – Unique identifier for the agent

  • username (str) – The agent’s username

  • role (str) – The agent’s role in the simulation

  • leaning (str) – Political or ideological leaning of the agent

  • age (int) – Age of the agent

  • personality (dict) – Big Five personality traits (Openness, Conscientiousness, Extraversion, Agreeableness, Neuroticism)

  • recsys (dict) – Recommendation system preferences (content-based and social-based weights)

  • language (str) – Primary language of the agent

  • education (str) – Education level of the agent

  • joined (int) – Round/time when the agent joined the simulation

  • gender (str) – Gender of the agent

  • nationality (str) – Nationality of the agent

  • toxicity (float) – Toxicity level of the agent’s behavior

  • is_page (bool) – Whether the agent is a page (organizational account) or individual

  • left_on (int) – Round/time when the agent left the simulation (if applicable)

  • daily_activity_level (float) – Activity level of the agent per day

  • profession (str) – Professional occupation of the agent

Example

Creating an agent from a database row:

from ysights.models.Agents import Agent

# Example database row
row = (1, 'alice_smith', None, None, 'user', 'moderate', 32,
       0.7, 0.6, 0.8, 0.5, 0.4, 0.5, 'en', None, 'college',
       0, 0.5, 'female', 'USA', 0.1, False, None, 3.5, 'teacher')

agent = Agent(row)
print(f"Agent ID: {agent.id}")
print(f"Username: {agent.username}")
print(f"Personality: {agent.personality}")
print(f"Age: {agent.age}, Gender: {agent.gender}")

See also

Agents: Collection class for managing multiple agents

__init__(row)[source]
class ysights.models.Agents.Agents[source]

Bases: object

A container class for managing a collection of Agent objects.

This class provides methods to add agents to the collection and retrieve the list of agents. It serves as a convenient way to group and manipulate multiple agents from a YSocial simulation.

Variables:

agents (list) – Internal list storing all Agent objects

Example

Managing a collection of agents:

from ysights import YDataHandler
from ysights.models.Agents import Agents, Agent

# Create an agents collection
agents = Agents()

# Add agents to the collection
row1 = (1, 'alice', None, None, 'user', 'left', 25, 0.7, 0.6, 0.8, 0.5, 0.4,
        0.5, 'en', None, 'college', 0, 0.5, 'female', 'USA', 0.1, False,
        None, 3.5, 'teacher')
agent1 = Agent(row1)
agents.add_agent(agent1)

# Or retrieve from database
ydh = YDataHandler('path/to/database.db')
all_agents = ydh.agents()

# Get list of all agents
agent_list = all_agents.get_agents()
print(f"Total agents: {len(agent_list)}")

# Iterate through agents
for agent in agent_list:
    print(f"{agent.username}: {agent.role}")

See also

Agent: Individual agent class ysights.models.YDataHandler.YDataHandler.agents(): Retrieve agents from database

__init__()[source]

Initialize an empty Agents collection.

add_agent(agent)[source]

Add an agent to the collection.

Parameters:

agent (Agent) – The Agent object to add to the collection

Example:

agents = Agents()
agent = Agent(row_data)
agents.add_agent(agent)
get_agents()[source]

Retrieve the list of all agents in the collection.

Returns:

List of all Agent objects in this collection

Return type:

list[Agent]

Example:

agents = Agents()
# ... add agents ...
agent_list = agents.get_agents()
for agent in agent_list:
    print(agent.username)

Post Classes

Classes for representing posts and post collections.

class ysights.models.Posts.Post(row)[source]

Bases: object

Represents a social media post in the YSocial simulation.

This class encapsulates all properties of a post including text content, metadata, and enriched features such as sentiment, hashtags, topics, mentions, emotions, toxicity scores, and reactions.

Parameters:

row (tuple) – A database row tuple containing post data in a specific order: [id, text, ?, user_id, comment_to, thread_id, round, news_id, shared_from, image_id]

Variables:
  • id (int) – Unique identifier for the post

  • text (str) – The text content of the post

  • user_id (int) – ID of the agent who created the post

  • comment_to (int) – ID of the post this is commenting on (None if not a comment)

  • thread_id (int) – ID of the thread this post belongs to

  • round (int) – Simulation round when the post was created

  • news_id (int) – ID of the news article this post references (if applicable)

  • shared_from (int) – ID of the original post if this is a share

  • image_id (int) – ID of the attached image (if applicable)

  • sentiment (dict) – Sentiment analysis scores (neg, pos, neu, compound)

  • hashtags (list) – List of hashtags used in the post

  • topics (list) – List of topics associated with the post

  • mentions (list) – List of user IDs mentioned in the post

  • toxicity (dict) – Toxicity scores across multiple dimensions

  • emotions (list) – List of emotions detected in the post

  • reactions (dict) – Dictionary mapping reaction types to their counts

Example

Creating and enriching a post:

from ysights.models.Posts import Post
from ysights import YDataHandler

# Example database row
row = (123, 'Hello world! #greeting', None, 5, None, 1, 10, None, None, None)
post = Post(row)

print(f"Post ID: {post.id}")
print(f"Text: {post.text}")
print(f"Author: {post.user_id}")

# Enrich post with additional data from database
# (requires database cursor)
ydh = YDataHandler('path/to/database.db')
posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['sentiment', 'hashtags'])

for post in posts.get_posts():
    print(f"Sentiment: {post.sentiment}")
    print(f"Hashtags: {post.hashtags}")

See also

Posts: Collection class for managing multiple posts enrich_post(): Method to enrich post with additional data

__init__(row)[source]

Initialize a Post object with data from a database row.

Parameters:

row (tuple) – Database row containing post data

enrich_post(cursor, dimensions=['all'])[source]

Enrich the post with additional data from the database.

This method retrieves and attaches additional information to the post based on specified dimensions. Each dimension corresponds to a different type of metadata that can be retrieved from the database.

Parameters:
  • cursor (sqlite3.Cursor) – Database cursor for executing queries

  • dimensions (list[str]) – List of dimensions to enrich. Options include: ‘sentiment’, ‘hashtags’, ‘mentions’, ‘emotions’, ‘topics’, ‘toxicity’, ‘reactions’, or ‘all’ for everything

Raises:

ValueError – If an unknown dimension is specified

Example:

from ysights import YDataHandler

ydh = YDataHandler('path/to/database.db')

# Enrich with specific dimensions
posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['sentiment', 'hashtags'])

# Or enrich with all available data
all_posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['all'])

for post in all_posts.get_posts():
    print(f"Sentiment: {post.sentiment}")
    print(f"Topics: {post.topics}")
    print(f"Emotions: {post.emotions}")
    print(f"Reactions: {dict(post.reactions)}")

Note

The ‘all’ dimension will enrich the post with all available metadata, which may be slower but provides complete information.

class ysights.models.Posts.Posts[source]

Bases: object

A container class for managing a collection of Post objects.

This class provides methods to add posts to the collection and retrieve the list of posts. It serves as a convenient way to group and manipulate multiple posts from a YSocial simulation.

Variables:

posts (list) – Internal list storing all Post objects

Example

Managing a collection of posts:

from ysights import YDataHandler
from ysights.models.Posts import Posts, Post

# Create a posts collection
posts = Posts()

# Add posts manually
row = (1, 'Hello world!', None, 5, None, 1, 10, None, None, None)
post = Post(row)
posts.add_post(post)

# Or retrieve posts from database
ydh = YDataHandler('path/to/database.db')
agent_posts = ydh.posts_by_agent(agent_id=5, enrich_dimensions=['sentiment'])

# Get list of all posts
post_list = agent_posts.get_posts()
print(f"Total posts: {len(post_list)}")

# Iterate through posts
for post in post_list:
    print(f"Post {post.id}: {post.text[:50]}...")
    if post.sentiment:
        print(f"  Sentiment: {post.sentiment}")

See also

Post: Individual post class ysights.models.YDataHandler.YDataHandler.posts(): Retrieve all posts from database ysights.models.YDataHandler.YDataHandler.posts_by_agent(): Retrieve posts by specific agent

__init__()[source]

Initialize an empty Posts collection.

add_post(post)[source]

Add a post to the collection.

Parameters:

post (Post) – The Post object to add to the collection

Example:

posts = Posts()
post = Post(row_data)
posts.add_post(post)
get_posts()[source]

Retrieve the list of all posts in the collection.

Returns:

List of all Post objects in this collection

Return type:

list[Post]

Example:

posts = Posts()
# ... add posts ...
post_list = posts.get_posts()
for post in post_list:
    print(f"{post.id}: {post.text}")