267 lines
12 KiB
Python
267 lines
12 KiB
Python
#!/bin/python3
|
|
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import os
|
|
|
|
def plotData(conf):
|
|
plt.clf()
|
|
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, conf["yaxismax"]/4, conf["textBox"], fontsize=10, verticalalignment='top', bbox=props)
|
|
for i in range(len(conf["data"])):
|
|
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")
|
|
|
|
|
|
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 __get_attrbs__(self, result):
|
|
text = str(result.shape).split("-")
|
|
d = dict()
|
|
for i in range(0, len(text), 2):
|
|
d[text[i]] = text[i + 1]
|
|
return d
|
|
|
|
def plotHeatmaps(self, x, y):
|
|
"""Plot the heatmap using the parameters given as x axis and y axis"""
|
|
print("Plotting heatmap "+x+" vs "+y)
|
|
#Find the location of x in shape
|
|
#Find the location of y in shape
|
|
#Find the location od r in shape
|
|
|
|
#Loop over all results
|
|
#Add unique values foir every parameter
|
|
|
|
#Find number of runs from r
|
|
#If number of values for x and y > 3 then plot heatmap, otherwise finish
|
|
|
|
#Create a 2D grid with the dimensions of the number of values for x and y
|
|
#For all values of x
|
|
#For all values of y
|
|
# For all values in r
|
|
#Fixing all other values to 1 (in the mean time)
|
|
#Add/sum TTA into 2D grid
|
|
#if last r divide by number of runs
|
|
|
|
#Plot 2D grid
|
|
|
|
|
|
|
|
|
|
def plotAll(self):
|
|
"""Plot all the important elements of each result"""
|
|
for result in self.results:
|
|
plotPath = "results/"+self.execID+"/plots/"+str(result.shape)
|
|
os.makedirs(plotPath, exist_ok=True)
|
|
self.plotMissingSamples(result, plotPath)
|
|
self.plotProgress(result, plotPath)
|
|
self.plotSentData(result, plotPath)
|
|
self.plotRecvData(result, plotPath)
|
|
self.plotDupData(result, plotPath)
|
|
if self.config.saveRCdist:
|
|
self.plotRowCol(result, plotPath)
|
|
|
|
def plotMissingSamples(self, result, plotPath):
|
|
"""Plots the missing samples in the network"""
|
|
conf = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
conf["title"] = "Missing Samples"
|
|
conf["type"] = "plot"
|
|
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"] = plotPath+"/missingSamples.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 plotProgress(self, result, plotPath):
|
|
"""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"]
|
|
vector4 = result.metrics["progress"]["DASampling progress (query all)"]
|
|
vector5 = result.metrics["progress"]["DASampling progress (query 3)"]
|
|
vector6 = result.metrics["progress"]["DASampling progress (query 2)"]
|
|
vector7 = result.metrics["progress"]["DASampling progress (query 1)"]
|
|
vector8 = result.metrics["progress"]["DASampling ready (query all)"]
|
|
vector9 = result.metrics["progress"]["DASampling ready (query 3)"]
|
|
vector10 = result.metrics["progress"]["DASampling ready (query 2)"]
|
|
vector11 = result.metrics["progress"]["DASampling ready (query 1)"]
|
|
conf = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
conf["title"] = "Nodes/validators ready"
|
|
conf["type"] = "plot"
|
|
conf["legLoc"] = 2
|
|
conf["desLoc"] = 2
|
|
conf["colors"] = ["g-", "b-", "r-", "m-", "m--", "m-.", "m:", "c-", "c--", "c-.", "c:"]
|
|
conf["labels"] = ["Nodes", "Validators", "Custody samples",
|
|
"DASampling progress (query all)", "DASampling progress (query 3)", "DASampling progress (query 2)", "DASampling progress (query 1)",
|
|
"DASampling ready (query all)", "DASampling ready (query 3)", "DASampling ready (query 2)", "DASampling ready (query 1)"]
|
|
conf["xlabel"] = "Time (ms)"
|
|
conf["ylabel"] = "Ratio of all (0..1)"
|
|
conf["data"] = [vector1, vector2, vector3, vector4, vector5, vector6, vector7, vector8, vector9, vector10, vector11 ]
|
|
conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))]
|
|
conf["path"] = plotPath+"/nodesReady.png"
|
|
conf["yaxismax"] = 1
|
|
plotData(conf)
|
|
print("Plot %s created." % conf["path"])
|
|
|
|
def plotSentData(self, result, plotPath):
|
|
"""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 = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
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"] = plotPath+"/sentData.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, plotPath):
|
|
"""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 = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
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"] = plotPath+"/recvData.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, plotPath):
|
|
"""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 = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
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"] = plotPath+"/dupData.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, plotPath):
|
|
"""Plots the percentage of nodes ready in the network"""
|
|
vector1 = result.metrics["rowDist"]
|
|
vector2 = result.metrics["columnDist"]
|
|
if len(vector1) > len(vector2):
|
|
vector2 += [np.nan] * (len(vector1) - len(vector2))
|
|
elif len(vector1) < len(vector2):
|
|
vector1 += [np.nan] * (len(vector2) - len(vector1))
|
|
conf = {}
|
|
attrbs = self.__get_attrbs__(result)
|
|
conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\
|
|
+"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd']
|
|
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"] = plotPath+"/RowColDist.png"
|
|
maxi = 0
|
|
for v in conf["data"]:
|
|
if np.nanmax(v) > maxi:
|
|
maxi = max(v)
|
|
conf["yaxismax"] = maxi
|
|
plotData(conf)
|
|
print("Plot %s created." % conf["path"])
|
|
|