<filename>code/visualization/visualizer.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
This script contains functions to visualize the development of the statistics 
over the total iterations per simulation and it contains functions to plot an 
arbitrary graph and all the graphs generated by all the simulations for a given 
human mobility algorithm.
"""

# Import built-in modules
import os

# Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx

def plot_metrics(algorithm, simulations, user_name):
    """
    This function collects all csv files generated by a specific algorithm and 
    user, calculates the averages and standard deviations for the three 
    statiscs for accuracy and shape metrics for each iteration moment and makes 
    a plot of the development over time for each of the statistcs and saves 
    them to specific file for the given user.

    Input:
        algorithm = algorithm for human mobility
        simulations = the total amount of simulations performed
        user_name = name of the user who ran the simulations

    Output:
        Plots are saved in a folder specified by results_{user_name}/algorithm
    """

    # Create relative file path to results folder and to the csv files
    alg_path = os.path.join(f"results_{user_name}", algorithm)
    path = os.path.join(alg_path, "datacollector_sim")

    # Load all csv files into a dataframe and store each of them in a list.
    dfs = [pd.read_csv(path + str(sim) + ".csv") for sim in range(simulations)]

    # Determine the amount of observation per variable and create tracking 
    # varibales for the three statistics for accuracy and shape metrics
    size = dfs[0]["Accuracy"].size
    all_accuracies, all_shape = [], []
    
    # Collects all values for each of the statistics seperately
    nr_stats = 3
    for variable in range(nr_stats):
        var_accuracy = [[] for _ in range(size)]
        var_shape = [[] for _ in range(size)]
        for df in dfs:
            for obs in range(size):
                accuracy = df[["Accuracy"]].iloc[obs][0]
                shapes = df[["Shape"]].iloc[obs][0]
                acc_preproccesed = accuracy.strip("(),").split(",")
                shapes_preproccesed = shapes.strip("(),").split(",")
                number = float(acc_preproccesed[variable])
                number2 = float(shapes_preproccesed[variable])
                var_accuracy[obs].append(number), var_shape[obs].append(number2)
        all_accuracies.append(var_accuracy), all_shape.append(var_shape)

    # Determine the averages and standard deviation of each of the statistics
    ave_accuracies, ave_shapes = [[], [], []], [[], [], []]
    stds_accuracies, stds_shapes = [[], [], []], [[], [], []]
    for variable in range(nr_stats):
        for acc, s in zip(all_accuracies[variable], all_shape[variable]):
            ave_accuracies[variable].append(np.mean(acc))
            ave_shapes[variable].append(np.mean(s))
            stds_accuracies[variable].append(np.std(acc))
            stds_shapes[variable].append(np.std(s))

    # Make plots for the accuracy statistics
    variables = ["Accuracy", "F1", "Mathews_Correlation_Coeffcient"]
    make_figure(algorithm, alg_path, variables, ave_accuracies, stds_accuracies)

    # Make plots for the shape metrics
    variables = ["Density", "Variance_degree", "Centrality"]
    make_figure(algorithm, alg_path, variables, ave_shapes, stds_shapes)

def make_figure(algorithm, alg_path, variables, averages, stds):
    """
    Makes plots of each of the statistics' averages and confidence interval 
    against the total iterations.

    Input:
        algorithm = human mobility algorithm
        alg_path = relative file path to save the figures
        variables = array-like containing the names of the statistics
        averages = nested list containing the averages of each statistic
        stds = nested list containing the standard deviations of each statistic
    Output:
        Saves figures to a folder specified by results_{user_name}/algorithm
    """
    
    # Makes a figure for each statistic
    for i, statistic in enumerate(averages):
        plt.figure()

        # Create values for x-axis (iterations) and make plot
        observations = len(statistic)
        x = [0.01 * i for i in range(observations)]
        plt.plot(x, statistic, color="darkblue")

        # Generate different title and x label for the different algorithms
        if algorithm == "SBLN":
            plt.title("Mean accuracy over all tests for Levy based walk")
            plt.xlabel("iteration number (10^5)")
        elif algorithm == "GRAV":
            plt.title("Mean accuracy over all tests for gravitywalk")
            plt.xlabel("iteration number (10^5)")
        elif algorithm == "BM":
            plt.title("Mean accuracy over all tests for Brownian Motion")
            plt.xlabel("iteration number (10^6)")

        # Create y label and plot confidence interval
        plt.ylabel(variables[i])
        plt.errorbar(
            x, statistic, yerr=stds[i], 
            alpha=0.1, color="cornflowerblue"
            )
        
        # Save figure to results folder, when done close figure
        plt.savefig(os.path.join(alg_path, 
                    f"plot_{algorithm}_{variables[i]}.pdf"), 
                    dpi=300
                    )
        plt.close()

def plot_network(road_dens, graph, user_name, gr_type):
    """
    Makes a plot of a specific graph.

    Input:
        road_dens = road denisty matrix of the area (numpy)
        graph = graph object (networkx)
        user_name = name of the user who ran the simulations (string)
        gr_type = name of the graph (string)
    Output:
        Saves files to a folder of the form results_{user_name}/algorithm
    """

    # Create relative file path to results folder 
    # and determine widht, height of area
    path = os.path.join(f"results_{user_name}", f"{gr_type}.pdf")
    width = road_dens.shape[1] - 1
    height = road_dens.shape[0] - 1

    # Draw graph with the nodes on thei positions and their size depending on 
    # it's nodal degree (amount of rivals)
    pos = nx.get_node_attributes(graph, "pos")
    d = dict(graph.degree)
    nx.draw(graph, pos, node_size=[(v + 1) * 5 for v in d.values()])

    # Set x, y limits and title graph. If done save figure and close figure
    plt.xlim(0, width)
    plt.ylim(0, height)
    plt.title(f"{gr_type}")
    plt.savefig(path, dpi=300)
    plt.close()

def plot_networks(algorithm, simulations, config, user_name):
    """
    Makes figures of the graphs generated at the end of each simulation by a 
    certain user.

    Input:
        algorithm = human mobility algorithm
        simulations = total amount of simulations that the model has ran
        config = object containing the configuration of the model
        user_name = name of the user who ran the simulations
    """

    # Create relative file path to results folder 
    # and to load each rivalry matrix
    alg_path = os.path.join(f"results_{user_name}", algorithm)
    path = os.path.join(alg_path, "rivalry_matrix_sim")

    # Load all rivalry matrices
    matrices_sim = [np.load(path + str(sim) + ".npy") 
                    for sim in range(simulations)]

    # Determine width and height of the area (Hollenbeck)
    width = config.road_dens.shape[1] - 1
    height = config.road_dens.shape[0] - 1

    # Create graph for each of the rivalry matrices
    shape = len(config.gang_info)
    for mat, matrix in enumerate(matrices_sim):

        # Initialize graph with the nodes (gangs) at their home locations
        graph = nx.Graph()
        for gang in config.gang_info.values():
            graph.add_node(gang.number, pos=gang.coords)

        # Determines if the rivalry between gangs is larger than a threshold. 
        # If so add edge as confirmation of the rivalry
        for i in range(shape):
            total_interactions = matrix[i, :].sum()
            for j in range(shape):
                if total_interactions:
                    rival_strength = matrix[i][j] / total_interactions
                    if rival_strength > config.parameters["threshold"]:
                        graph.add_edge(i, j, color=config.colors[i])
        
        # Draw graph with the nodes at their location and their size depending 
        # on the nodal degree (amount of rivals)
        pos = nx.get_node_attributes(graph, "pos")
        d = dict(graph.degree)
        nx.draw(graph, pos, node_size=[(v + 1) * 5 for v in d.values()])

        # Plots a differen title depending on the human mobility algorithm
        if algorithm == "GRAV":
            plt.title("Network Gravity model")
        elif algorithm == "SBLN":
            plt.title("Network Semi-Biased Levy walk")
        elif algorithm == "BM":
            plt.title("Network Brownian Motion")

        # Set limits axis and save figure to folder. If done close figure
        plt.xlim(0, width)
        plt.ylim(0, height)
        plt.savefig(os.path.join(alg_path, f"network_sim{mat}.pdf"), dpi=300)
        plt.close()

<filename>code/visualization/visualizer.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
This script contains functions to visualize the development of the statistics 
over the total iterations per simulation and it contains functions to plot an 
arbitrary graph and all the graphs generated by all the simulations for a given 
human mobility algorithm.
"""

# Import built-in modules
import os

# Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx

def plot_metrics(algorithm, simulations, user_name):
    """
    This function collects all csv files generated by a specific algorithm and 
    user, calculates the averages and standard deviations for the three 
    statiscs for accuracy and shape metrics for each iteration moment and makes 
    a plot of the development over time for each of the statistcs and saves 
    them to specific file for the given user.

    Input:
        algorithm = algorithm for human mobility
        simulations = the total amount of simulations performed
        user_name = name of the user who ran the simulations

    Output:
        Plots are saved in a folder specified by results_{user_name}/algorithm
    """

    # Create relative file path to results folder and to the csv files
    alg_path = os.path.join(f"results_{user_name}", algorithm)
    path = os.path.join(alg_path, "datacollector_sim")

    # Load all csv files into a dataframe and store each of them in a list.
    dfs = [pd.read_csv(path + str(sim) + ".csv") for sim in range(simulations)]

    # Determine the amount of observation per variable and create tracking 
    # varibales for the three statistics for accuracy and shape metrics
    size = dfs[0]["Accuracy"].size
    all_accuracies, all_shape = [], []
    
    # Collects all values for each of the statistics seperately
    nr_stats = 3
    for variable in range(nr_stats):
        var_accuracy = [[] for _ in range(size)]
        var_shape = [[] for _ in range(size)]
        for df in dfs:
            for obs in range(size):
                accuracy = df[["Accuracy"]].iloc[obs][0]
                shapes = df[["Shape"]].iloc[obs][0]
                acc_preproccesed = accuracy.strip("(),").split(",")
                shapes_preproccesed = shapes.strip("(),").split(",")
                number = float(acc_preproccesed[variable])
                number2 = float(shapes_preproccesed[variable])
                var_accuracy[obs].append(number), var_shape[obs].append(number2)
        all_accuracies.append(var_accuracy), all_shape.append(var_shape)

    # Determine the averages and standard deviation of each of the statistics
    ave_accuracies, ave_shapes = [[], [], []], [[], [], []]
    stds_accuracies, stds_shapes = [[], [], []], [[], [], []]
    for variable in range(nr_stats):
        for acc, s in zip(all_accuracies[variable], all_shape[variable]):
            ave_accuracies[variable].append(np.mean(acc))
            ave_shapes[variable].append(np.mean(s))
            stds_accuracies[variable].append(np.std(acc))
            stds_shapes[variable].append(np.std(s))

    # Make plots for the accuracy statistics
    variables = ["Accuracy", "F1", "Mathews_Correlation_Coeffcient"]
    make_figure(algorithm, alg_path, variables, ave_accuracies, stds_accuracies)

    # Make plots for the shape metrics
    variables = ["Density", "Variance_degree", "Centrality"]
    make_figure(algorithm, alg_path, variables, ave_shapes, stds_shapes)

def make_figure(algorithm, alg_path, variables, averages, stds):
    """
    Makes plots of each of the statistics' averages and confidence interval 
    against the total iterations.

    Input:
        algorithm = human mobility algorithm
        alg_path = relative file path to save the figures
        variables = array-like containing the names of the statistics
        averages = nested list containing the averages of each statistic
        stds = nested list containing the standard deviations of each statistic
    Output:
        Saves figures to a folder specified by results_{user_name}/algorithm
    """
    
    # Makes a figure for each statistic
    for i, statistic in enumerate(averages):
        plt.figure()

        # Create values for x-axis (iterations) and make plot
        observations = len(statistic)
        x = [0.01 * i for i in range(observations)]
        plt.plot(x, statistic, color="darkblue")

        # Generate different title and x label for the different algorithms
        if algorithm == "SBLN":
            plt.title("Mean accuracy over all tests for Levy based walk")
            plt.xlabel("iteration number (10^5)")
        elif algorithm == "GRAV":
            plt.title("Mean accuracy over all tests for gravitywalk")
            plt.xlabel("iteration number (10^5)")
        elif algorithm == "BM":
            plt.title("Mean accuracy over all tests for Brownian Motion")
            plt.xlabel("iteration number (10^6)")

        # Create y label and plot confidence interval
        plt.ylabel(variables[i])
        plt.errorbar(
            x, statistic, yerr=stds[i], 
            alpha=0.1, color="cornflowerblue"
            )
        
        # Save figure to results folder, when done close figure
        plt.savefig(os.path.join(alg_path, 
                    f"plot_{algorithm}_{variables[i]}.pdf"), 
                    dpi=300
                    )
        plt.close()

def plot_network(road_dens, graph, user_name, gr_type):
    """
    Makes a plot of a specific graph.

    Input:
        road_dens = road denisty matrix of the area (numpy)
        graph = graph object (networkx)
        user_name = name of the user who ran the simulations (string)
        gr_type = name of the graph (string)
    Output:
        Saves files to a folder of the form results_{user_name}/algorithm
    """

    # Create relative file path to results folder 
    # and determine widht, height of area
    path = os.path.join(f"results_{user_name}", f"{gr_type}.pdf")
    width = road_dens.shape[1] - 1
    height = road_dens.shape[0] - 1

    # Draw graph with the nodes on thei positions and their size depending on 
    # it's nodal degree (amount of rivals)
    pos = nx.get_node_attributes(graph, "pos")
    d = dict(graph.degree)
    nx.draw(graph, pos, node_size=[(v + 1) * 5 for v in d.values()])

    # Set x, y limits and title graph. If done save figure and close figure
    plt.xlim(0, width)
    plt.ylim(0, height)
    plt.title(f"{gr_type}")
    plt.savefig(path, dpi=300)
    plt.close()

def plot_networks(algorithm, simulations, config, user_name):
    """
    Makes figures of the graphs generated at the end of each simulation by a 
    certain user.

    Input:
        algorithm = human mobility algorithm
        simulations = total amount of simulations that the model has ran
        config = object containing the configuration of the model
        user_name = name of the user who ran the simulations
    """

    # Create relative file path to results folder 
    # and to load each rivalry matrix
    alg_path = os.path.join(f"results_{user_name}", algorithm)
    path = os.path.join(alg_path, "rivalry_matrix_sim")

    # Load all rivalry matrices
    matrices_sim = [np.load(path + str(sim) + ".npy") 
                    for sim in range(simulations)]

    # Determine width and height of the area (Hollenbeck)
    width = config.road_dens.shape[1] - 1
    height = config.road_dens.shape[0] - 1

    # Create graph for each of the rivalry matrices
    shape = len(config.gang_info)
    for mat, matrix in enumerate(matrices_sim):

        # Initialize graph with the nodes (gangs) at their home locations
        graph = nx.Graph()
        for gang in config.gang_info.values():
            graph.add_node(gang.number, pos=gang.coords)

        # Determines if the rivalry between gangs is larger than a threshold. 
        # If so add edge as confirmation of the rivalry
        for i in range(shape):
            total_interactions = matrix[i, :].sum()
            for j in range(shape):
                if total_interactions:
                    rival_strength = matrix[i][j] / total_interactions
                    if rival_strength > config.parameters["threshold"]:
                        graph.add_edge(i, j, color=config.colors[i])
        
        # Draw graph with the nodes at their location and their size depending 
        # on the nodal degree (amount of rivals)
        pos = nx.get_node_attributes(graph, "pos")
        d = dict(graph.degree)
        nx.draw(graph, pos, node_size=[(v + 1) * 5 for v in d.values()])

        # Plots a differen title depending on the human mobility algorithm
        if algorithm == "GRAV":
            plt.title("Network Gravity model")
        elif algorithm == "SBLN":
            plt.title("Network Semi-Biased Levy walk")
        elif algorithm == "BM":
            plt.title("Network Brownian Motion")

        # Set limits axis and save figure to folder. If done close figure
        plt.xlim(0, width)
        plt.ylim(0, height)
        plt.savefig(os.path.join(alg_path, f"network_sim{mat}.pdf"), dpi=300)
        plt.close()

#!/usr/bin/env python # -*- coding: utf-8 -*- This script contains functions to visualize the development of the statistics  over the total iterations per simulation and it contains functions to plot an  arbitrary graph and all the graphs generated by all the simulations for a given  human mobility algorithm. # Import built-in modules # Import libraries This function collects all csv files generated by a specific algorithm and      user, calculates the averages and standard deviations for the three      statiscs for accuracy and shape metrics for each iteration moment and makes      a plot of the development over time for each of the statistcs and saves      them to specific file for the given user.      Input:         algorithm = algorithm for human mobility         simulations = the total amount of simulations performed         user_name = name of the user who ran the simulations      Output:         Plots are saved in a folder specified by results_{user_name}/algorithm # Create relative file path to results folder and to the csv files # Load all csv files into a dataframe and store each of them in a list. # Determine the amount of observation per variable and create tracking # varibales for the three statistics for accuracy and shape metrics # Collects all values for each of the statistics seperately # Determine the averages and standard deviation of each of the statistics # Make plots for the accuracy statistics # Make plots for the shape metrics Makes plots of each of the statistics' averages and confidence interval      against the total iterations.      Input:         algorithm = human mobility algorithm         alg_path = relative file path to save the figures         variables = array-like containing the names of the statistics         averages = nested list containing the averages of each statistic         stds = nested list containing the standard deviations of each statistic     Output:         Saves figures to a folder specified by results_{user_name}/algorithm # Makes a figure for each statistic # Create values for x-axis (iterations) and make plot # Generate different title and x label for the different algorithms # Create y label and plot confidence interval # Save figure to results folder, when done close figure Makes a plot of a specific graph.      Input:         road_dens = road denisty matrix of the area (numpy)         graph = graph object (networkx)         user_name = name of the user who ran the simulations (string)         gr_type = name of the graph (string)     Output:         Saves files to a folder of the form results_{user_name}/algorithm # Create relative file path to results folder # and determine widht, height of area # Draw graph with the nodes on thei positions and their size depending on # it's nodal degree (amount of rivals) # Set x, y limits and title graph. If done save figure and close figure Makes figures of the graphs generated at the end of each simulation by a      certain user.      Input:         algorithm = human mobility algorithm         simulations = total amount of simulations that the model has ran         config = object containing the configuration of the model         user_name = name of the user who ran the simulations # Create relative file path to results folder # and to load each rivalry matrix # Load all rivalry matrices # Determine width and height of the area (Hollenbeck) # Create graph for each of the rivalry matrices # Initialize graph with the nodes (gangs) at their home locations # Determines if the rivalry between gangs is larger than a threshold. # If so add edge as confirmation of the rivalry # Draw graph with the nodes at their location and their size depending # on the nodal degree (amount of rivals) # Plots a differen title depending on the human mobility algorithm # Set limits axis and save figure to folder. If done close figure