Skip to content
Snippets Groups Projects
Generate_results_CSV.py 8.18 KiB
"""
Visualize results from the computation prepared by Generate_input_for_HQ.py
"""

import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import os
import json
import sys
import argparse
import warnings
import re


# Copied from https://stackoverflow.com/questions/11150239/natural-sorting
def natural_sort(l):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [convert(c) for c in re.split("([0-9]+)", key)]
    return sorted(l, key=alphanum_key)


def generate_plot(df_best, vehicle_type_names, name_of_folder, number_of_iter):
    df_best_extended = pd.DataFrame({})
    how_many_vehicle_types = 0
    for col in df_best.columns:
        if "Vehicle Type" in col:
            how_many_vehicle_types += 1

    pd_index = 0
    for row in range(len(df_best)):
        for type in range(how_many_vehicle_types):
            key_name = "Vehicle Type " + vehicle_type_names[type]
            for add_row in range(df_best[key_name].iloc[row]):
                df_row = pd.DataFrame(
                    {
                        "Problem Name": df_best["Problem Name"].iloc[row],
                        "Vehicle Type": key_name,
                    },
                    index=[pd_index],
                )
                pd_index += 1
                df_best_extended = pd.concat([df_row, df_best_extended])
    if df_best_extended.empty:
        return
    # df_best_extended.to_csv("df_best_extended.csv")
    plt.clf()
    plt.figure(figsize=(20, 12))
    # number_of_colors = df_best_extended["Vehicle Type"].nunique()
    pallete = {}
    for i in range(len(vehicle_type_names)):
        pallete.update(
            {"Vehicle Type " + vehicle_type_names[i]: sns.color_palette()[i]}
        )
    chart = sns.histplot(
        df_best_extended,
        x="Problem Name",
        hue="Vehicle Type",
        multiple="dodge",
        shrink=0.8,
        palette=pallete,
    )
    sns.set(rc={"figure.figsize": (17, 10)})

    ticks_loc = chart.get_xticks()
    chart.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
    chart.set_xticklabels(
        chart.get_xticklabels(),
        ha="center",
        fontsize=14,
    )

    # mpl.rcParams["figure.figsize"] = 5, 25
    # plt.show()
    # plt.legend(title="Vehicles", labels=vehicle_type_names)
    plt.savefig(
        name_of_folder
        + "/plots_Problem_"
        + str(df_best["Problem Name"].iloc[0])
        + "_Fleet_"
        + str(df_best["Fleet Composition ID"].iloc[0])
        + ".png",
        bbox_inches="tight",
    )
    plt.close()
    return


def generate_full_results(
    problem_name, used_fleet, vroom_output, df_final, fleet_index, given_index
):
    """Appending row to dataframe"""
    served_all = "F"
    if vroom_output["summary"]["unassigned"] == 0:
        served_all = "T"
    type_count = []
    for add_zeros in range(len(used_fleet)):
        type_count.append(0)
    start_ind = 0
    used_fleet = list(used_fleet.split(","))
    used_fleet[0] = used_fleet[0].replace("[", "")
    used_fleet[len(used_fleet) - 1] = used_fleet[len(used_fleet) - 1].replace("]", "")
    for used in range(len(used_fleet)):
        used_fleet[used] = int(used_fleet[used])

    for type in range(len(type_count)):
        for routes in vroom_output["routes"]:
            if routes["vehicle"] == type + 1:
                type_count[type] += 1

    df_row = pd.DataFrame(
        {
            "Problem Name": problem_name,
            "Fleet Composition ID": fleet_index + 1,
            "Total Cost": [vroom_output["summary"]["cost"]],
            "Total Duration": [vroom_output["summary"]["duration"]],
            "Served All Shipments": served_all,
        },
        index=[given_index],
    )

    for fleet in range(len(used_fleet)):
        vehicle_type = "Vehicle Type " + str(fleet + 1)
        df_row[vehicle_type] = type_count[fleet]
    df_final = pd.concat([df_final, df_row])
    return df_final


# Parse arguments
parser = argparse.ArgumentParser()

parser.add_argument(
    "-i",
    "--inputfolder",
    required=True,
    help=("Path to input files. Usually output " "file of HyperQueue VROOM run."),
)
parser.add_argument(
    "-o",
    "--outputfolder",
    default="output/results",
    help="Path to output files. Defaults to output/results",
)
parser.add_argument(
    "-r",
    "--helperfolder",
    default="output/vis_helper",
    help=("Path to visualization helper files." "Created by Generate_input_for_HQ.py"),
)

args = parser.parse_args()

# Get environment variables
current_path = os.getcwd()

input_folder = os.path.join(current_path, args.inputfolder)
output_folder = os.path.join(current_path, args.outputfolder)
plots_folder = os.path.join(output_folder, "plots")
helper_folder = os.path.join(current_path, args.helperfolder)

if not os.path.exists(input_folder):
    raise ValueError("Input folder given in --inputfolder does not exists.")
if not os.path.exists(helper_folder):
    raise ValueError("Input folder given in --helperfolder does not exists.")
if not os.path.exists(output_folder):
    os.mkdir(output_folder)
if not os.path.exists(plots_folder):
    os.mkdir(plots_folder)

# Read helper files
file1 = open(os.path.join(helper_folder, "Used_fleets.txt"), "r")
data1 = file1.read()
used_fleets = data1.split("\n")
used_fleets.pop()

file2 = open(os.path.join(helper_folder, "Problem_names.txt"), "r")
data2 = file2.read()
problem_names = data2.split("\n")
problem_names.pop()

# used vehicle types
file3 = open(os.path.join(helper_folder, "Vehicle_names.txt"), "r")
data3 = file3.read()
vehicle_type_names = data3.split("\n")
vehicle_type_names.pop()

for vehicle_type in range(len(vehicle_type_names)):
    vehicle_type_names[vehicle_type] = vehicle_type_names[vehicle_type].replace("'", "")

df_final = pd.DataFrame({})

# Read input json
list_of_files_unsorted = os.listdir(input_folder)
list_of_files_unsorted = [x for x in list_of_files_unsorted if ".json" in x]

if len(list_of_files_unsorted) == 1:
    list_of_files = list_of_files_unsorted
elif len(list_of_files_unsorted) > 1:
    list_of_files = natural_sort(list_of_files_unsorted)
else:
    raise ValueError("No input JSON files found! Check --inputfolder argument")

list_of_vroom_results = []

for file in list_of_files:
    json_file = open(input_folder + "/" + file, "r")
    data = json_file.read()
    json_file.close()
    list_of_vroom_results.append(json.loads(data))

fleet_index = 0
given_index = 0
for fleet in used_fleets:
    for problem in problem_names:
        df_final = generate_full_results(
            problem,
            fleet,
            list_of_vroom_results[given_index],
            df_final,
            fleet_index,
            given_index,
        )
        given_index += 1
    fleet_index += 1

# print(problem_names)
skip_these = []
df_best = pd.DataFrame({})
new_row = pd.DataFrame({})
# new_index = 0
for i in problem_names:
    am_i_the_lowest = sys.maxsize
    for j in range(len(df_final)):
        if df_final["Problem Name"].iloc[j] in skip_these:
            continue
        if (
            df_final["Total Cost"].iloc[j] < am_i_the_lowest
            and df_final["Problem Name"].iloc[j] == i
            and df_final["Served All Shipments"].iloc[j] == "T"
        ):
            new_row = df_final.iloc[[j]]
            am_i_the_lowest = df_final["Total Cost"].iloc[j]
    skip_these.append(i)
    if new_row.empty:
        continue
    df_best = pd.concat([df_best, new_row], ignore_index=True)

columns_to_rename = []
for col in df_final.columns:
    if "Vehicle Type" in col:
        columns_to_rename.append(col)
for x in range(len(columns_to_rename)):
    df_final = df_final.rename(
        columns={columns_to_rename[x]: "Vehicle Type " + vehicle_type_names[x]}
    )
    if df_best.empty:
        continue
    df_best = df_best.rename(
        columns={columns_to_rename[x]: "Vehicle Type " + vehicle_type_names[x]}
    )

df_best.to_csv(os.path.join(output_folder, "df_best.csv"))
df_final.to_csv(os.path.join(output_folder, "df_all.csv"))

number_of_iters = len(df_final)
for i in range(number_of_iters):
    df_current = pd.DataFrame({})
    df_current = df_final.loc[[i]]
    df_current = df_current.reset_index(drop=True)
    generate_plot(df_current, vehicle_type_names, os.path.join(plots_folder), i)