From 20c68cf1981367338e15cf1e5a584e46f36d54e1 Mon Sep 17 00:00:00 2001 From: leobago Date: Sat, 13 May 2023 11:25:09 +0200 Subject: [PATCH 1/2] New visualizer module WIP --- DAS/__init__.py | 1 + DAS/visualizor.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++ study.py | 3 ++ 3 files changed, 84 insertions(+) create mode 100644 DAS/visualizor.py diff --git a/DAS/__init__.py b/DAS/__init__.py index 67af3ae..84c1246 100644 --- a/DAS/__init__.py +++ b/DAS/__init__.py @@ -1,3 +1,4 @@ from DAS.simulator import * from DAS.shape import * from DAS.visualizer import * +from DAS.visualizor import * diff --git a/DAS/visualizor.py b/DAS/visualizor.py new file mode 100644 index 0000000..caa05d1 --- /dev/null +++ b/DAS/visualizor.py @@ -0,0 +1,80 @@ +#!/bin/python3 + +import matplotlib.pyplot as plt +import os + +def plotData(conf): + plt.clf() + fig = plt.figure("6, 3") + if conf["desLoc"] == 1: + xDes = 0 + else: + xDes = conf["xdots"][-1] * 0.6 + props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) + plt.text(xDes, max(conf["data"][0])/4, conf["textBox"], fontsize=10, verticalalignment='top', bbox=props) + for i in range(len(conf["data"])): + plt.plot(conf["xdots"], conf["data"][i], conf["colors"][i], label=conf["labels"][i]) + plt.title(conf["title"]) + plt.ylabel(conf["ylabel"]) + plt.xlabel(conf["xlabel"]) + plt.legend(loc=conf["legLoc"]) + plt.savefig(conf["path"], bbox_inches="tight") + + +class Visualizor: + """This class helps the visualization of the results""" + + def __init__(self, execID, config, results): + """Initialize the visualizer module""" + self.execID = execID + self.config = config + self.results = results + os.makedirs("results/"+self.execID+"/plots", exist_ok=True) + + def plotAll(self): + """Plot all the important elements of each result""" + for result in self.results: + self.plotMissingSamples(result) + self.plotProgress(result) + + def plotMissingSamples(self, result): + """Plots the missing samples in the network""" + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Missing Samples" + conf["legLoc"] = 1 + conf["desLoc"] = 1 + conf["colors"] = ["m-"] + conf["labels"] = ["Missing Samples"] + conf["xlabel"] = "Time (ms)" + conf["ylabel"] = "Number of Missing Samples" + conf["data"] = [result.missingVector] + conf["xdots"] = [x*self.config.stepDuration for x in range(len(result.missingVector))] + conf["path"] = "results/"+self.execID+"/plots/missingSamples-"+str(result.shape)+".png" + plotData(conf) + print("Plot %s created." % conf["path"]) + + def plotProgress(self, result): + """Plots the percentage of nodes ready in the network""" + vector1 = result.metrics["progress"]["nodes ready"] + vector2 = result.metrics["progress"]["validators ready"] + vector3 = result.metrics["progress"]["samples received"] + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Nodes/validators ready" + conf["legLoc"] = 2 + conf["desLoc"] = 2 + conf["colors"] = ["g-", "b-", "r-"] + conf["labels"] = ["Nodes", "Validators", "Samples"] + conf["xlabel"] = "Time (ms)" + conf["ylabel"] = "Percentage (%)" + conf["data"] = [vector1, vector2, vector3] + conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] + conf["path"] = "results/"+self.execID+"/plots/nodesReady-"+str(result.shape)+".png" + plotData(conf) + print("Plot %s created." % conf["path"]) + diff --git a/study.py b/study.py index badb7f3..fff5205 100644 --- a/study.py +++ b/study.py @@ -87,5 +87,8 @@ def study(): vis = Visualizer(execID, config) vis.plotHeatmaps() + visual = Visualizor(execID, config, results) + visual.plotAll() + if __name__ == "__main__": study() From f1db022e17a206b892bfbd004d064068aa135814 Mon Sep 17 00:00:00 2001 From: leobago Date: Mon, 15 May 2023 17:56:30 +0200 Subject: [PATCH 2/2] Fix row and column distribution --- DAS/visualizor.py | 145 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 3 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index caa05d1..b3147f2 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -5,18 +5,22 @@ import os def plotData(conf): plt.clf() - fig = plt.figure("6, 3") + fig = plt.figure("9, 3") if conf["desLoc"] == 1: xDes = 0 else: xDes = conf["xdots"][-1] * 0.6 props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) - plt.text(xDes, max(conf["data"][0])/4, conf["textBox"], fontsize=10, verticalalignment='top', bbox=props) + plt.text(xDes, conf["yaxismax"]/4, conf["textBox"], fontsize=10, verticalalignment='top', bbox=props) for i in range(len(conf["data"])): - plt.plot(conf["xdots"], conf["data"][i], conf["colors"][i], label=conf["labels"][i]) + if conf["type"] == "plot": + plt.plot(conf["xdots"], conf["data"][i], conf["colors"][i], label=conf["labels"][i]) + if conf["type"] == "bar": + plt.bar(conf["xdots"], conf["data"][i], label=conf["labels"][i]) plt.title(conf["title"]) plt.ylabel(conf["ylabel"]) plt.xlabel(conf["xlabel"]) + plt.ylim(0, conf["yaxismax"]*1.1) plt.legend(loc=conf["legLoc"]) plt.savefig(conf["path"], bbox_inches="tight") @@ -36,6 +40,10 @@ class Visualizor: for result in self.results: self.plotMissingSamples(result) self.plotProgress(result) + self.plotSentData(result) + self.plotRecvData(result) + self.plotDupData(result) + self.plotRowCol(result) def plotMissingSamples(self, result): """Plots the missing samples in the network""" @@ -44,6 +52,7 @@ class Visualizor: conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" conf["title"] = "Missing Samples" + conf["type"] = "plot" conf["legLoc"] = 1 conf["desLoc"] = 1 conf["colors"] = ["m-"] @@ -53,6 +62,11 @@ class Visualizor: conf["data"] = [result.missingVector] conf["xdots"] = [x*self.config.stepDuration for x in range(len(result.missingVector))] conf["path"] = "results/"+self.execID+"/plots/missingSamples-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi plotData(conf) print("Plot %s created." % conf["path"]) @@ -66,6 +80,7 @@ class Visualizor: conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" conf["title"] = "Nodes/validators ready" + conf["type"] = "plot" conf["legLoc"] = 2 conf["desLoc"] = 2 conf["colors"] = ["g-", "b-", "r-"] @@ -75,6 +90,130 @@ class Visualizor: conf["data"] = [vector1, vector2, vector3] conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] conf["path"] = "results/"+self.execID+"/plots/nodesReady-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi + plotData(conf) + print("Plot %s created." % conf["path"]) + + def plotSentData(self, result): + """Plots the percentage of nodes ready in the network""" + vector1 = result.metrics["progress"]["TX builder mean"] + vector2 = result.metrics["progress"]["TX class1 mean"] + vector3 = result.metrics["progress"]["TX class2 mean"] + for i in range(len(vector1)): + vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + vector3[i] = (vector3[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Sent data" + conf["type"] = "plot" + conf["legLoc"] = 2 + conf["desLoc"] = 2 + conf["colors"] = ["y-", "c-", "m-"] + conf["labels"] = ["Block Builder", "Solo stakers", "Staking pools"] + conf["xlabel"] = "Time (ms)" + conf["ylabel"] = "Bandwidth (MBits/s)" + conf["data"] = [vector1, vector2, vector3] + conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] + conf["path"] = "results/"+self.execID+"/plots/sentData-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi + plotData(conf) + print("Plot %s created." % conf["path"]) + + def plotRecvData(self, result): + """Plots the percentage of nodes ready in the network""" + vector1 = result.metrics["progress"]["RX class1 mean"] + vector2 = result.metrics["progress"]["RX class2 mean"] + for i in range(len(vector1)): + vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Received data" + conf["type"] = "plot" + conf["legLoc"] = 2 + conf["desLoc"] = 2 + conf["colors"] = ["c-", "m-"] + conf["labels"] = ["Solo stakers", "Staking pools"] + conf["xlabel"] = "Time (ms)" + conf["ylabel"] = "Bandwidth (MBits/s)" + conf["data"] = [vector1, vector2] + conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] + conf["path"] = "results/"+self.execID+"/plots/recvData-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi + plotData(conf) + print("Plot %s created." % conf["path"]) + + def plotDupData(self, result): + """Plots the percentage of nodes ready in the network""" + vector1 = result.metrics["progress"]["Dup class1 mean"] + vector2 = result.metrics["progress"]["Dup class2 mean"] + for i in range(len(vector1)): + vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Duplicated data" + conf["type"] = "plot" + conf["legLoc"] = 2 + conf["desLoc"] = 2 + conf["colors"] = ["c-", "m-"] + conf["labels"] = ["Solo stakers", "Staking pools"] + conf["xlabel"] = "Time (ms)" + conf["ylabel"] = "Bandwidth (MBits/s)" + conf["data"] = [vector1, vector2] + conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] + conf["path"] = "results/"+self.execID+"/plots/dupData-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi + plotData(conf) + print("Plot %s created." % conf["path"]) + + def plotRowCol(self, result): + """Plots the percentage of nodes ready in the network""" + vector1 = result.metrics["rowDist"] + vector2 = result.metrics["columnDist"] + conf = {} + text = str(result.shape).split("-") + conf["textBox"] = "Block Size: "+text[1]+"\nNumber of nodes: "+text[3]\ + +"\nFailure rate: "+text[7]+" \nNetwork degree: "+text[23]+"\nX: "+text[11]+" rows/columns" + conf["title"] = "Row/Column distribution" + conf["type"] = "bar" + conf["legLoc"] = 2 + conf["desLoc"] = 2 + conf["colors"] = ["r+", "b+"] + conf["labels"] = ["Rows", "Columns"] + conf["xlabel"] = "Row/Column ID" + conf["ylabel"] = "Validators subscribed" + conf["data"] = [vector1, vector2] + conf["xdots"] = range(len(vector1)) + conf["path"] = "results/"+self.execID+"/plots/RowColDist-"+str(result.shape)+".png" + maxi = 0 + for v in conf["data"]: + if max(v) > maxi: + maxi = max(v) + conf["yaxismax"] = maxi plotData(conf) print("Plot %s created." % conf["path"])