visualizor.py
1 #!/bin/python3 2 3 import matplotlib.pyplot as plt 4 import numpy as np 5 import os 6 7 def plotData(conf): 8 plt.clf() 9 fig = plt.figure("9, 3") 10 if conf["desLoc"] == 1: 11 xDes = 0 12 else: 13 xDes = conf["xdots"][-1] * 0.6 14 props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) 15 plt.text(xDes, conf["yaxismax"]/4, conf["textBox"], fontsize=10, verticalalignment='top', bbox=props) 16 for i in range(len(conf["data"])): 17 if conf["type"] == "plot": 18 plt.plot(conf["xdots"], conf["data"][i], conf["colors"][i], label=conf["labels"][i]) 19 if conf["type"] == "bar": 20 plt.bar(conf["xdots"], conf["data"][i], label=conf["labels"][i]) 21 plt.title(conf["title"]) 22 plt.ylabel(conf["ylabel"]) 23 plt.xlabel(conf["xlabel"]) 24 plt.ylim(0, conf["yaxismax"]*1.1) 25 plt.legend(loc=conf["legLoc"]) 26 plt.savefig(conf["path"], bbox_inches="tight") 27 28 29 class Visualizor: 30 """This class helps the visualization of the results""" 31 32 def __init__(self, execID, config, results): 33 """Initialize the visualizer module""" 34 self.execID = execID 35 self.config = config 36 self.results = results 37 os.makedirs("results/"+self.execID+"/plots", exist_ok=True) 38 39 def __get_attrbs__(self, result): 40 text = str(result.shape).split("-") 41 d = dict() 42 for i in range(0, len(text), 2): 43 d[text[i]] = text[i + 1] 44 return d 45 46 def plotHeatmaps(self, x, y): 47 """Plot the heatmap using the parameters given as x axis and y axis""" 48 print("Plotting heatmap "+x+" vs "+y) 49 #Find the location of x in shape 50 #Find the location of y in shape 51 #Find the location od r in shape 52 53 #Loop over all results 54 #Add unique values foir every parameter 55 56 #Find number of runs from r 57 #If number of values for x and y > 3 then plot heatmap, otherwise finish 58 59 #Create a 2D grid with the dimensions of the number of values for x and y 60 #For all values of x 61 #For all values of y 62 # For all values in r 63 #Fixing all other values to 1 (in the mean time) 64 #Add/sum TTA into 2D grid 65 #if last r divide by number of runs 66 67 #Plot 2D grid 68 69 70 71 72 def plotAll(self): 73 """Plot all the important elements of each result""" 74 for result in self.results: 75 plotPath = "results/"+self.execID+"/plots/"+str(result.shape) 76 os.makedirs(plotPath, exist_ok=True) 77 self.plotMissingSamples(result, plotPath) 78 self.plotProgress(result, plotPath) 79 self.plotSentData(result, plotPath) 80 self.plotRecvData(result, plotPath) 81 self.plotDupData(result, plotPath) 82 if self.config.saveRCdist: 83 self.plotRowCol(result, plotPath) 84 85 def plotMissingSamples(self, result, plotPath): 86 """Plots the missing samples in the network""" 87 conf = {} 88 attrbs = self.__get_attrbs__(result) 89 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 90 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 91 conf["title"] = "Missing Samples" 92 conf["type"] = "plot" 93 conf["legLoc"] = 1 94 conf["desLoc"] = 1 95 conf["colors"] = ["m-"] 96 conf["labels"] = ["Missing Samples"] 97 conf["xlabel"] = "Time (ms)" 98 conf["ylabel"] = "Number of Missing Samples" 99 conf["data"] = [result.missingVector] 100 conf["xdots"] = [x*self.config.stepDuration for x in range(len(result.missingVector))] 101 conf["path"] = plotPath+"/missingSamples.png" 102 maxi = 0 103 for v in conf["data"]: 104 if max(v) > maxi: 105 maxi = max(v) 106 conf["yaxismax"] = maxi 107 plotData(conf) 108 print("Plot %s created." % conf["path"]) 109 110 def plotProgress(self, result, plotPath): 111 """Plots the percentage of nodes ready in the network""" 112 vector1 = result.metrics["progress"]["nodes ready"] 113 vector2 = result.metrics["progress"]["validators ready"] 114 vector3 = result.metrics["progress"]["samples received"] 115 conf = {} 116 attrbs = self.__get_attrbs__(result) 117 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 118 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 119 conf["title"] = "Nodes/validators ready" 120 conf["type"] = "plot" 121 conf["legLoc"] = 2 122 conf["desLoc"] = 2 123 conf["colors"] = ["g-", "b-", "r-"] 124 conf["labels"] = ["Nodes", "Validators", "Samples"] 125 conf["xlabel"] = "Time (ms)" 126 conf["ylabel"] = "Percentage (%)" 127 conf["data"] = [vector1, vector2, vector3] 128 conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] 129 conf["path"] = plotPath+"/nodesReady.png" 130 maxi = 0 131 for v in conf["data"]: 132 if max(v) > maxi: 133 maxi = max(v) 134 conf["yaxismax"] = maxi 135 plotData(conf) 136 print("Plot %s created." % conf["path"]) 137 138 def plotSentData(self, result, plotPath): 139 """Plots the percentage of nodes ready in the network""" 140 vector1 = result.metrics["progress"]["TX builder mean"] 141 vector2 = result.metrics["progress"]["TX class1 mean"] 142 vector3 = result.metrics["progress"]["TX class2 mean"] 143 for i in range(len(vector1)): 144 vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 145 vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 146 vector3[i] = (vector3[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 147 conf = {} 148 attrbs = self.__get_attrbs__(result) 149 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 150 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 151 conf["title"] = "Sent data" 152 conf["type"] = "plot" 153 conf["legLoc"] = 2 154 conf["desLoc"] = 2 155 conf["colors"] = ["y-", "c-", "m-"] 156 conf["labels"] = ["Block Builder", "Solo stakers", "Staking pools"] 157 conf["xlabel"] = "Time (ms)" 158 conf["ylabel"] = "Bandwidth (MBits/s)" 159 conf["data"] = [vector1, vector2, vector3] 160 conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] 161 conf["path"] = plotPath+"/sentData.png" 162 maxi = 0 163 for v in conf["data"]: 164 if max(v) > maxi: 165 maxi = max(v) 166 conf["yaxismax"] = maxi 167 plotData(conf) 168 print("Plot %s created." % conf["path"]) 169 170 def plotRecvData(self, result, plotPath): 171 """Plots the percentage of nodes ready in the network""" 172 vector1 = result.metrics["progress"]["RX class1 mean"] 173 vector2 = result.metrics["progress"]["RX class2 mean"] 174 for i in range(len(vector1)): 175 vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 176 vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 177 conf = {} 178 attrbs = self.__get_attrbs__(result) 179 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 180 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 181 conf["title"] = "Received data" 182 conf["type"] = "plot" 183 conf["legLoc"] = 2 184 conf["desLoc"] = 2 185 conf["colors"] = ["c-", "m-"] 186 conf["labels"] = ["Solo stakers", "Staking pools"] 187 conf["xlabel"] = "Time (ms)" 188 conf["ylabel"] = "Bandwidth (MBits/s)" 189 conf["data"] = [vector1, vector2] 190 conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] 191 conf["path"] = plotPath+"/recvData.png" 192 maxi = 0 193 for v in conf["data"]: 194 if max(v) > maxi: 195 maxi = max(v) 196 conf["yaxismax"] = maxi 197 plotData(conf) 198 print("Plot %s created." % conf["path"]) 199 200 def plotDupData(self, result, plotPath): 201 """Plots the percentage of nodes ready in the network""" 202 vector1 = result.metrics["progress"]["Dup class1 mean"] 203 vector2 = result.metrics["progress"]["Dup class2 mean"] 204 for i in range(len(vector1)): 205 vector1[i] = (vector1[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 206 vector2[i] = (vector2[i] * 8 * (1000/self.config.stepDuration) * self.config.segmentSize) / 1000000 207 conf = {} 208 attrbs = self.__get_attrbs__(result) 209 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 210 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 211 conf["title"] = "Duplicated data" 212 conf["type"] = "plot" 213 conf["legLoc"] = 2 214 conf["desLoc"] = 2 215 conf["colors"] = ["c-", "m-"] 216 conf["labels"] = ["Solo stakers", "Staking pools"] 217 conf["xlabel"] = "Time (ms)" 218 conf["ylabel"] = "Bandwidth (MBits/s)" 219 conf["data"] = [vector1, vector2] 220 conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] 221 conf["path"] = plotPath+"/dupData.png" 222 maxi = 0 223 for v in conf["data"]: 224 if max(v) > maxi: 225 maxi = max(v) 226 conf["yaxismax"] = maxi 227 plotData(conf) 228 print("Plot %s created." % conf["path"]) 229 230 def plotRowCol(self, result, plotPath): 231 """Plots the percentage of nodes ready in the network""" 232 vector1 = result.metrics["rowDist"] 233 vector2 = result.metrics["columnDist"] 234 if len(vector1) > len(vector2): 235 vector2 += [np.nan] * (len(vector1) - len(vector2)) 236 elif len(vector1) < len(vector2): 237 vector1 += [np.nan] * (len(vector2) - len(vector1)) 238 conf = {} 239 attrbs = self.__get_attrbs__(result) 240 conf["textBox"] = "Block Size R: "+attrbs['bsrn']+"\nBlock Size C: "+attrbs['bscn']\ 241 +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+" \nNetwork degree: "+attrbs['nd'] 242 conf["title"] = "Row/Column distribution" 243 conf["type"] = "bar" 244 conf["legLoc"] = 2 245 conf["desLoc"] = 2 246 conf["colors"] = ["r+", "b+"] 247 conf["labels"] = ["Rows", "Columns"] 248 conf["xlabel"] = "Row/Column ID" 249 conf["ylabel"] = "Validators subscribed" 250 conf["data"] = [vector1, vector2] 251 conf["xdots"] = range(len(vector1)) 252 conf["path"] = plotPath+"/RowColDist.png" 253 maxi = 0 254 for v in conf["data"]: 255 if np.nanmax(v) > maxi: 256 maxi = max(v) 257 conf["yaxismax"] = maxi 258 plotData(conf) 259 print("Plot %s created." % conf["path"]) 260