Skip to content
Snippets Groups Projects
Commit 05c4ac37 authored by ArktikHunter's avatar ArktikHunter
Browse files

gui creates or modifies config file,

which gets read by example to run sim
parent a37d0114
No related branches found
No related tags found
1 merge request!21pydtn agkmeans and version 1.0
"""GUI for pydtnsim"""
__author__ = "Hunter McConnell <hunter.mcconnell@usask.ca"
import sys
import csv
import yaml
from argparse import ArgumentParser
from collections import namedtuple
from multiprocessing import Pool
from os import path
from random import randint
import gui
from pydtnsim import Network, RandomTraffic, Node, EpidemicNode, CSVTrace
from pydtnsim.community import BubbleKCliqueNode, BubbleLouvainNode
from pydtnsim.community import HCBFKCliqueNode, HCBFLouvainNode
Simulation = namedtuple('Simulation', ['trace', 'node_type', 'seed'])
# Implement nodes (clustering, routing combos) in community.py
# lifted from examples/shed.py
def run_simulation(simulation):
"""Run a simulation."""
seed = simulation.seed
csv = path.join(simulation.trace, 'contact.csv')
metadata = path.join(simulation.trace, 'metadata.json')
trace = CSVTrace(csv, metadata=metadata)
epoch = 7*24*60*60 # 7 days var: how often clusters are recalculated
node_type = simulation.node_type
node_options = {
'tick_rate': 5 * 60, # 5 mins var:
'epoch': epoch,
'k': 3, # var: k value for k means clustering
'context': {}
}
nodes = {
node_id: simulation.node_type(**node_options)
for node_id in range(trace.nodes)
}
traffic_options = {
'seed': seed,
'start': epoch,
'step': 60 * 60, # 1 min var: how often packets are created
}
traffic = RandomTraffic(nodes, **traffic_options) # var: random traffic, see init for other options
network = Network(nodes, traffic=traffic, trace=trace)
network.run()
stats = {
'trace': simulation.trace,
'node_type': node_type.__name__,
'seed': seed,
}
stats.update(network.stats_summary)
return stats
def run_all_sims():
pool = Pool()
simulations = []
#trace = args['shed']
pass
# puts up the GUI, or reads from config, then runs the sims
def main(args):
if args['no_gui']:
with open("example.yaml", 'r', newline='') as f:
config = yaml.load(f, Loader=yaml.FullLoader)
else:
# put up GUI for user input
config = gui.main(args)
print(config)
# todo: run the sim lol
def parse_args(args):
"""Parse arguments."""
parser = ArgumentParser()
parser.add_argument('--no_gui', '-n', action='store_true',
help="skips the gui and reads from config file provided")
parser.add_argument('--config', '-c', help="config file to read from", default="config.yaml")
args = parser.parse_args(args)
return vars(args)
if __name__ == '__main__':
sys.exit(main(parse_args(sys.argv[1:])))
\ No newline at end of file
"""GUI testing"""
__author__ = "Hunter McConnell <hunter.mcconnell@usask.ca"
import os
import sys
import itertools
import yaml
from tkinter import *
from tkinter.ttk import *
from yaml.loader import Loader
from pydtnsim import Node, EpidemicNode
from pydtnsim.community import BubbleKCliqueNode, BubbleLouvainNode
from pydtnsim.community import HCBFKCliqueNode, HCBFLouvainNode
def main(args={"config":"config.yaml"}):
# base window
root = Tk()
root.title("PyDtnSim")
root.geometry("800x400")
# frames 1-3 divide window into thirds
frame1 = LabelFrame(root, borderwidth=2, text="Frame1", height=200, width=100)
frame1.grid(row=0, column=1)
frame2 = LabelFrame(root, borderwidth=2, text="Sim", height=200, width=100)
frame2.grid(row=0, column=0)
frame3 = LabelFrame(root, borderwidth=2, text="Frame3", height=200, width=100)
frame3.grid(row=0, column=2)
# contains the node checkboxes
frame_nodes = Frame(frame1)
frame_nodes.grid(row=0, column=1)
# node selection
Label(frame1, text="Nodes:").grid(row=0, column=0)
NODES = [
Node, # direct delivery
EpidemicNode,
BubbleKCliqueNode,
HCBFKCliqueNode,
BubbleLouvainNode,
HCBFLouvainNode
]
node_vars = []
for (i, node) in zip(range(len(NODES)), NODES):
v = IntVar()
node_vars.append(v)
Checkbutton(frame_nodes, text=node.__name__, variable=v).pack(fill=X)
Label(frame2, text="Name:").grid(row=0, column=0)
name_var = StringVar()
name_var.set("config")
Entry(frame2, textvariable=name_var).grid(row=0, column=1)
# contact trace location
# todo: file dialog?
# todo: validation?
Label(frame2, text="Contact file:").grid(row=1, column=0)
trace_var = StringVar()
Entry(frame2, textvariable=trace_var).grid(row=1, column=1)
# output file
# todo: file dialog?
# todo: validation?
Label(frame2, text="Output file:").grid(row=2, column=0)
out_var = StringVar()
Entry(frame2, textvariable=out_var).grid(row=2, column=1)
# batch number
# todo: validation?
Label(frame2, text="# of batches:").grid(row=3, column=0)
batch_var = IntVar(value=1)
Entry(frame2, textvariable=batch_var).grid(row=3, column=1)
# seeds
Label(frame2, text="Seeds:").grid(row=4, column=0)
seeds_var = StringVar()
Entry(frame2, textvariable=seeds_var).grid(row=4, column=1)
# epoch
Label(frame1, text="Epoch (sec):").grid(row=2, column=0)
epoch_var = IntVar(value=604800)
Entry(frame1, textvariable=epoch_var).grid(row=2, column=1)
# tick_rate? or shouldn't this be equal to duty cycles?
# k for k means clustering
Label(frame1, text="k:").grid(row=3, column=0)
k_var = IntVar(value=3)
Entry(frame1, textvariable=k_var).grid(row=3, column=1)
# packet creation rate
Label(frame3, text="Packet Generation Interval (sec):").grid(row=1, column=0)
generation_var = IntVar(value=300)
Entry(frame3, textvariable=generation_var).grid(row=1, column=1)
# traffic type
# reads the given config file and allows editing of its values
def read_config(file_name):
with open(file_name, 'r', newline='') as f:
param = yaml.load(f, Loader=Loader)
#todo: nodes
if "name" in param: name_var.set(param["name"])
if "trace" in param: trace_var.set(param["trace"])
if "output" in param: out_var.set(param["output"])
if "batch" in param: batch_var.set(param["batch"])
if "seeds" in param:
tmp = ', '.join(str(i) for i in param["seeds"])
seeds_var.set(tmp) #todo: works? string -> list -> string
if "epoch" in param: epoch_var.set(param["epoch"])
# read in config file if is exists
if os.path.exists(args["config"]):
read_config(args["config"])
# fills a dict with config values, then dumps to file to read later
def submit(param):
# todo: validation, must choose at least one node
param["name"] = name_var.get()
param["nodes"] = []
for (node, var) in zip(NODES, node_vars):
if var.get() == 1:
param["nodes"].append(node)
param["trace"] = trace_var.get()
param["output"] = out_var.get()
param["batch"] = batch_var.get()
# transforms the entry string into a list of ints ^.^
param["seeds"] = [int(seed.strip()) for seed in seeds_var.get().split(',') if seed != '']
param["epoch"] = epoch_var.get()
with open(f"{name_var.get()}.yaml", 'w', newline='') as f:
yaml.dump(param, f)
msg.set(name_var.get() + " saved")
param = {}
Button(root, text="Save sim parameters", command=lambda: submit(param)).grid(row=1, column=0, columnspan=3)
Button(root, text="Close and run sim", command=root.quit).grid(row=2, column=0, columnspan=3)
msg = StringVar(value=" ")
Label(root, textvariable=msg).grid(row=3, column=0, columnspan=3)
root.mainloop()
return param
if __name__ == '__main__':
sys.exit(main())
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment