From 7c769f800b9ca24784b073d1699864a3916d271a Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Mon, 18 Mar 2024 22:58:53 +0000 Subject: [PATCH 01/22] Segment Size field in plot textbox & Implemented Heatmap of NetDegree vs NoOfNodes on Simulation Runtime --- DAS/visualizor.py | 135 ++++++++++++++++++++++++++++++++++------------ study.py | 1 + 2 files changed, 103 insertions(+), 33 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 073980c..808b0ab 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -4,6 +4,7 @@ import matplotlib.pyplot as plt import seaborn as sns import numpy as np import os +import pandas as pd def plotData(conf): plt.clf() @@ -171,7 +172,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Box Plot of Restore Row Count by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Restore Row Count" @@ -197,7 +199,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Box Plot of Restore Column Count by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Restore Column Count" @@ -223,7 +226,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Boxen Plot of Restore Row Count by Nodes" conf["xlabel"] = "Restore Row Count" conf["ylabel"] = "Nodes" @@ -247,7 +251,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Boxen Plot of Restore Column Count by Nodes" conf["xlabel"] = "Restore Column Count" conf["ylabel"] = "Nodes" @@ -271,7 +276,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Restore Row Count by Nodes" conf["xlabel"] = "Restore Row Count" conf["ylabel"] = "ECDF" @@ -299,7 +305,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Restore Column Count by Nodes" conf["xlabel"] = "Restore Column Count" conf["ylabel"] = "ECDF" @@ -327,7 +334,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Messages Sent by Nodes" conf["xlabel"] = "Number of Messages Sent" conf["ylabel"] = "ECDF" @@ -354,7 +362,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Messages Received by Nodes" conf["xlabel"] = "Number of Messages Received" conf["ylabel"] = "ECDF" @@ -381,7 +390,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Samples Received by Nodes" conf["xlabel"] = "Number of Samples Received" conf["ylabel"] = "ECDF" @@ -408,7 +418,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Row-Col Distribution by Nodes" conf["xlabel"] = "Row-Col Distribution" conf["ylabel"] = "ECDF" @@ -435,7 +446,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Samples Repaired by Nodes" conf["xlabel"] = "Number of Samples Repaired" conf["ylabel"] = "ECDF" @@ -462,7 +474,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Received by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Number of Samples Received" @@ -488,7 +501,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Number of Samples Repaired" @@ -514,7 +528,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column Distribution" conf["xlabel"] = "Row/Column Type" conf["ylabel"] = "Validators Subscribed" @@ -545,7 +560,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Number of Messages Sent" @@ -569,7 +585,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Number of Messages Received" @@ -593,7 +610,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -614,7 +632,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column Distribution" conf["xlabel"] = "" conf["ylabel"] = "Validators Subscribed" @@ -637,7 +656,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Restore Row Count for Each Node" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -659,7 +679,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Restore Column Count for Each Node" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -681,7 +702,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Percentage of Samples Received by Nodes" conf["type"] = "individual_bar_with_2line" conf["legLoc"] = 1 @@ -716,7 +738,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Received by Nodes" conf["type"] = "individual_bar_with_2line" conf["legLoc"] = 1 @@ -737,7 +760,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Sample: "+str(min(result.missingVector) * 100 / max(result.missingVector))+"%" conf["title"] = "Missing Samples" conf["type"] = "plot_with_1line" conf["legLoc"] = 1 @@ -770,7 +794,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Nodes/validators ready" conf["type"] = "plot" conf["legLoc"] = 2 @@ -804,7 +829,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Sent data" conf["type"] = "plot" conf["legLoc"] = 2 @@ -836,7 +862,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Received data" conf["type"] = "plot" conf["legLoc"] = 2 @@ -868,7 +895,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Duplicated data" conf["type"] = "plot" conf["legLoc"] = 2 @@ -901,7 +929,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column distribution" conf["type"] = "grouped_bar" conf["legLoc"] = 2 @@ -928,7 +957,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -950,7 +980,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" conf["xlabel"] = "Node Type" conf["ylabel"] = "Number of Messages Sent" @@ -967,7 +998,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -989,7 +1021,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -1012,7 +1045,8 @@ class Visualizor: conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ - +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ + +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" conf["type"] = "individual_bar" conf["legLoc"] = 1 @@ -1026,3 +1060,38 @@ class Visualizor: conf["yaxismax"] = maxi plotData(conf) print("Plot %s created." % conf["path"]) + + def plotHeatMapData(self, conf): + data = {'x': conf['x'], 'y': conf['y'], 'weights': conf['weights']} + df = pd.DataFrame(data) + pivot_df = df.pivot_table(index='y', columns='x', values='weights', aggfunc="sum") + sns.heatmap(pivot_df, annot=True, cmap='viridis', fmt='.0f') + plt.xlabel(conf['xlabel']) + plt.ylabel(conf['ylabel']) + plt.title(conf['title']) + plt.savefig(f"results/{self.execID}/heatmaps/{conf['path']}") + + # x -> network degree, y -> number of nodes, weights -> simulation duration + def plotNWDegVsNodeOnRuntime(self): + if len(self.results) < 2: return + + x, y, weights = [], [], [] + for result in self.results: + _netDegree = result.shape.netDegree + _nodes = result.shape.numberNodes + _duration = self.config.stepDuration * (len(result.missingVector) - 1) + x.append(_netDegree) + y.append(_nodes) + weights.append(_duration) + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Number of Nodes', + 'title': 'Heatmap of Net Degree, Number of Nodes & Simulation Runtime', + 'path': 'NWDegNodeDuration.png' + } + + self.plotHeatMapData(conf) diff --git a/study.py b/study.py index 380cf30..7656e33 100644 --- a/study.py +++ b/study.py @@ -93,6 +93,7 @@ def study(): visual = Visualizor(execID, config, results) visual.plotHeatmaps("nn", "fr") + visual.plotNWDegVsNodeOnRuntime() if __name__ == "__main__": study() From 1d14f9eab3d80f8877b020f6c88fe281a282fd19 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Tue, 19 Mar 2024 13:27:46 +0000 Subject: [PATCH 02/22] Corrected plot textbox --- DAS/visualizor.py | 66 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 808b0ab..d038ccf 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -171,7 +171,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Box Plot of Restore Row Count by Nodes" @@ -198,7 +198,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Box Plot of Restore Column Count by Nodes" @@ -225,7 +225,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Boxen Plot of Restore Row Count by Nodes" @@ -250,7 +250,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Boxen Plot of Restore Column Count by Nodes" @@ -275,7 +275,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Restore Row Count by Nodes" @@ -304,7 +304,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Restore Column Count by Nodes" @@ -333,7 +333,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Messages Sent by Nodes" @@ -361,7 +361,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Messages Received by Nodes" @@ -389,7 +389,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Samples Received by Nodes" @@ -417,7 +417,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Row-Col Distribution by Nodes" @@ -445,7 +445,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "ECDF of Samples Repaired by Nodes" @@ -473,7 +473,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Received by Nodes" @@ -500,7 +500,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" @@ -527,7 +527,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column Distribution" @@ -559,7 +559,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" @@ -584,7 +584,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" @@ -609,7 +609,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" @@ -631,7 +631,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column Distribution" @@ -655,7 +655,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Restore Row Count for Each Node" @@ -678,7 +678,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Restore Column Count for Each Node" @@ -701,7 +701,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Percentage of Samples Received by Nodes" @@ -737,7 +737,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Received by Nodes" @@ -759,7 +759,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Sample: "+str(min(result.missingVector) * 100 / max(result.missingVector))+"%" conf["title"] = "Missing Samples" @@ -793,7 +793,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Nodes/validators ready" @@ -828,7 +828,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Sent data" @@ -861,7 +861,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Received data" @@ -894,7 +894,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Duplicated data" @@ -928,7 +928,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Row/Column distribution" @@ -956,7 +956,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" @@ -979,7 +979,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Sent by Nodes" @@ -997,7 +997,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" @@ -1020,7 +1020,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Messages Received by Nodes" @@ -1044,7 +1044,7 @@ class Visualizor: attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ - +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"\nMalicious Node: "+attrbs['mn']+"\nNetwork degree: "+attrbs['nd']\ + +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ +"\nSegment Size: "+str(self.config.segmentSize) conf["title"] = "Number of Samples Repaired by Nodes" From 42356a8a398babad6f1726347e3e336c35040808 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Tue, 19 Mar 2024 20:58:35 +0000 Subject: [PATCH 03/22] plotNWDegVsNodeOnRuntime() function fixed return condition --- DAS/visualizor.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index d038ccf..1a850b9 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1073,16 +1073,11 @@ class Visualizor: # x -> network degree, y -> number of nodes, weights -> simulation duration def plotNWDegVsNodeOnRuntime(self): - if len(self.results) < 2: return - - x, y, weights = [], [], [] - for result in self.results: - _netDegree = result.shape.netDegree - _nodes = result.shape.numberNodes - _duration = self.config.stepDuration * (len(result.missingVector) - 1) - x.append(_netDegree) - y.append(_nodes) - weights.append(_duration) + x = [result.shape.netDegree for result in self.results] + y = [result.shape.numberNodes for result in self.results] + weights = [self.config.stepDuration * (len(result.missingVector) - 1) for result in self.results] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap conf = { 'x': x, From 1dae18a02249774dea2241c505b8075557483a43 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Tue, 19 Mar 2024 22:03:03 +0000 Subject: [PATCH 04/22] Added heatmaps of netDegree vs maliciousNodes on Missing Samples --- DAS/visualizor.py | 29 +++++++++++++++++++++++++++-- study.py | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 1a850b9..cc66a2a 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1070,6 +1070,7 @@ class Visualizor: plt.ylabel(conf['ylabel']) plt.title(conf['title']) plt.savefig(f"results/{self.execID}/heatmaps/{conf['path']}") + plt.clf() # x -> network degree, y -> number of nodes, weights -> simulation duration def plotNWDegVsNodeOnRuntime(self): @@ -1085,8 +1086,32 @@ class Visualizor: 'weights': weights, 'xlabel': 'Net Degree', 'ylabel': 'Number of Nodes', - 'title': 'Heatmap of Net Degree, Number of Nodes & Simulation Runtime', - 'path': 'NWDegNodeDuration.png' + 'title': 'Net Degree vs. Number of Nodes on Simulation Runtime', + 'path': 'NWDegVsNodeOnRuntime.png' + } + + self.plotHeatMapData(conf) + + # x -> network degree, y -> % of malicious nodes, weights -> no of missing samples + def plotNWDegVsMalNodeOnMissingSamples(self): + x = [result.shape.netDegree for result in self.results] + y = [result.shape.maliciousNodes for result in self.results] + weights = [result.missingVector[-1] for result in self.results] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Malicious Nodes (%)', + 'title': 'Net Degree vs Malicious Nodes (%) on Missing Samples', + 'path': 'NWDegVsMalNodeOnMissingSamples.png' } self.plotHeatMapData(conf) + + def plotAllHeatMaps(self): + self.plotNWDegVsNodeOnRuntime() + self.plotNWDegVsMalNodeOnMissingSamples() \ No newline at end of file diff --git a/study.py b/study.py index 7656e33..2aa6dc8 100644 --- a/study.py +++ b/study.py @@ -93,7 +93,7 @@ def study(): visual = Visualizor(execID, config, results) visual.plotHeatmaps("nn", "fr") - visual.plotNWDegVsNodeOnRuntime() + visual.plotAllHeatMaps() if __name__ == "__main__": study() From ebb41a84d17d574366094e12c0a3a9477bb7ced3 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Tue, 19 Mar 2024 23:11:15 +0000 Subject: [PATCH 05/22] Added heatmaps of netDegree vs failureRate on Missing Samples Signed-off-by: Arunima Chaudhuri --- DAS/visualizor.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index cc66a2a..8ffb331 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1111,7 +1111,28 @@ class Visualizor: } self.plotHeatMapData(conf) - + + # x -> network degree, y -> failure rate, weights -> no of missing samples + def plotNWDegVsFailureRateOnMissingSamples(self): + x = [result.shape.netDegree for result in self.results] + y = [result.shape.failureRate for result in self.results] + weights = [result.missingVector[-1] for result in self.results] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Failure Rate (%)', + 'title': 'Net Degree vs Failure Rate (%) on Missing Samples', + 'path': 'NWDegVsFailureRateOnMissingSamples.png' + } + + self.plotHeatMapData(conf) + def plotAllHeatMaps(self): self.plotNWDegVsNodeOnRuntime() - self.plotNWDegVsMalNodeOnMissingSamples() \ No newline at end of file + self.plotNWDegVsMalNodeOnMissingSamples() + self.plotNWDegVsFailureRateOnMissingSamples() \ No newline at end of file From ea689f22830a8177117514ed6de71d4639a080b5 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Wed, 20 Mar 2024 17:21:38 +0000 Subject: [PATCH 06/22] Updated seaborn version to fix a warning --- DAS/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DAS/requirements.txt b/DAS/requirements.txt index 76b14c7..43f8b1c 100644 --- a/DAS/requirements.txt +++ b/DAS/requirements.txt @@ -4,5 +4,5 @@ matplotlib==3.6.2 mplfinance==0.12.9b7 networkx==3.0 numpy==1.23.5 -seaborn==0.12.2 +seaborn==0.13.0 joblib==1.2.0 From d63a20bb23195422229556f0e53879dc729d11d2 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Fri, 22 Mar 2024 15:30:26 +0100 Subject: [PATCH 07/22] progress plot: always use y range 0..1 Signed-off-by: Csaba Kiraly --- DAS/visualizor.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 073980c..1d034d6 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -782,11 +782,7 @@ class Visualizor: conf["data"] = [vector1, vector2, vector3] conf["xdots"] = [x*self.config.stepDuration for x in range(len(vector1))] conf["path"] = plotPath+"/nodesReady.png" - maxi = 0 - for v in conf["data"]: - if max(v) > maxi: - maxi = max(v) - conf["yaxismax"] = maxi + conf["yaxismax"] = 1 plotData(conf) print("Plot %s created." % conf["path"]) From 705ab8a96283801ad1c9b095ea824ac8129bcbc0 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Sun, 24 Mar 2024 21:00:18 +0000 Subject: [PATCH 08/22] Implemented state saving and completion check using pickle files Signed-off-by: Arunima Chaudhuri --- DAS/simulator.py | 41 +++++++++++++++++++++++++++++++++++++++++ study.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/DAS/simulator.py b/DAS/simulator.py index 7d4b341..a932e97 100644 --- a/DAS/simulator.py +++ b/DAS/simulator.py @@ -9,6 +9,9 @@ from DAS.tools import * from DAS.results import * from DAS.observer import * from DAS.node import * +import os +import pickle +import uuid class Simulator: """This class implements the main DAS simulator.""" @@ -273,7 +276,9 @@ class Simulator: trafficStatsVector = [] malicious_nodes_not_added_count = 0 steps = 0 + unique_run_id = str(uuid.uuid4()) while(True): + vectors_data = [] missingVector.append(missingSamples) self.logger.debug("Expected Samples: %d" % expected, extra=self.format) self.logger.debug("Missing Samples: %d" % missingSamples, extra=self.format) @@ -350,7 +355,43 @@ class Simulator: self.logger.debug("The entire block is available at step %d, with failure rate %d !" % (steps, self.shape.failureRate), extra=self.format) missingVector.append(missingSamples) break + + for i in range(0, self.shape.numberNodes): + validator_data = { + 'validator_ID': self.validators[i].ID, + 'rowIDs': list(self.validators[i].rowIDs), + 'columnIDs': list(self.validators[i].columnIDs), + 'amImalicious': self.validators[i].amImalicious, + 'amIaddedToQueue': self.validators[i].amIaddedToQueue, + 'msgSentCount': self.validators[i].msgSentCount, + 'msgRecvCount': self.validators[i].msgRecvCount, + 'sampleSentCount': self.validators[i].sampleSentCount, + 'sampleRecvCount': self.validators[i].sampleRecvCount, + 'restoreRowCount': self.validators[i].restoreRowCount, + 'restoreColumnCount': self.validators[i].restoreColumnCount, + 'repairedSampleCount': self.validators[i].repairedSampleCount, + 'rowNeighbors': list(self.validators[i].rowNeighbors), + 'columnNeighbors': list(self.validators[i].columnNeighbors) + } + vectors_data.append(validator_data) + + vectors_data += (progressVector,missingVector) + backup_folder = f"results/{self.execID}/backup" + if not os.path.exists(backup_folder): + os.makedirs(backup_folder) + backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") + with open(backup_file, 'ab') as f: + pickle.dump(vectors_data, f) steps += 1 + + + backup_folder = f"results/{self.execID}/backup" + if not os.path.exists(backup_folder): + os.makedirs(backup_folder) + backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") + + with open(backup_file, 'ab') as f: # Open in append binary mode + pickle.dump("completed", f) for i in range(0,self.shape.numberNodes): if not self.validators[i].amIaddedToQueue : diff --git a/study.py b/study.py index 380cf30..6ade619 100644 --- a/study.py +++ b/study.py @@ -45,7 +45,50 @@ def runOnce(config, shape, execID): return result + +def check_simulation_completion(state_file): + backup_dir = os.path.join(os.path.dirname(state_file), "backup") + if not os.path.exists(backup_dir): + return False + + all_completed = True + for filename in sorted(os.listdir(backup_dir), reverse=True): # Iterate in reverse order + if not filename.endswith(".pkl"): + continue + full_path = os.path.join(backup_dir, filename) + try: + with open(full_path, 'rb') as f: + items = [] + while True: + try: + item = pickle.load(f) + items.append(item) # Load all items + except EOFError: # Reached end of file + break + last_item = items[-1] # Access the last item + # print(last_item) + if last_item != "completed": + all_completed = False + break # No need to continue checking other files + except (OSError, pickle.UnpicklingError) as e: + print(f"Error loading state from {full_path}: {e}") + all_completed = False # Treat errors as incomplete + break # No need to continue checking other files + return all_completed + + def study(): + restart_path = None + for arg in sys.argv[1:]: + if arg.startswith("--restart="): + restart_path = arg[len("--restart="):] + + if restart_path: + execID = restart_path.split("/")[1] + state_file = f"results/{execID}/backup" + print(check_simulation_completion(state_file)) + sys.exit(0) + if len(sys.argv) < 2: print("You need to pass a configuration file in parameter") exit(1) From 04090fd89b16c24b3b6c89e70ea27185ac7c12a2 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Tue, 26 Mar 2024 13:06:11 +0000 Subject: [PATCH 09/22] identify incomplete simulations Signed-off-by: Arunima Chaudhuri --- study.py | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/study.py b/study.py index 6ade619..7013d14 100644 --- a/study.py +++ b/study.py @@ -52,6 +52,7 @@ def check_simulation_completion(state_file): return False all_completed = True + incomplete_files = [] for filename in sorted(os.listdir(backup_dir), reverse=True): # Iterate in reverse order if not filename.endswith(".pkl"): continue @@ -69,12 +70,12 @@ def check_simulation_completion(state_file): # print(last_item) if last_item != "completed": all_completed = False - break # No need to continue checking other files + incomplete_files.append(full_path) except (OSError, pickle.UnpicklingError) as e: print(f"Error loading state from {full_path}: {e}") all_completed = False # Treat errors as incomplete break # No need to continue checking other files - return all_completed + return all_completed, incomplete_files def study(): @@ -86,8 +87,40 @@ def study(): if restart_path: execID = restart_path.split("/")[1] state_file = f"results/{execID}/backup" - print(check_simulation_completion(state_file)) - sys.exit(0) + all_completed, incomplete_files = check_simulation_completion(state_file) + if all_completed: + print("Simulation is already completed.") + sys.exit(0) # Exit gracefully if already completed + else: + print(incomplete_files) + # Load the state (if available) + # all_results = [] + # for incomplete_file in incomplete_files: + # latest_state = None + # try: + # with open(incomplete_file, 'rb') as f: + # items = [] + # while True: + # try: + # item = pickle.load(f) + # items.append(item) + # except EOFError: + # break + # latest_state = items[-1] # Assuming state is the last item + # except (OSError, pickle.UnpicklingError) as e: + # print(f"Error loading state from {incomplete_file}: {e}") + # if latest_state: + # try: + # # Assuming configuration file is 'smallConf.py' + # config = importlib.import_module("smallConf") + # results = Parallel(config.numJobs)(delayed(runOnce)(config, shape, execID, latest_state) for shape in config.nextShape()) + # all_results.extend(results) # Collect results from all restarts + # except ModuleNotFoundError as e: + # print(f"Error importing configuration file 'smallConf.py': {e}") + # else: + # print(f"No state found for restart from {incomplete_file}. Skipping.") + + sys.exit(0) if len(sys.argv) < 2: print("You need to pass a configuration file in parameter") From ec0f9cc7818d74963e98061f544ef18f9026592a Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Tue, 26 Mar 2024 13:08:38 +0000 Subject: [PATCH 10/22] Clear code Signed-off-by: Arunima Chaudhuri --- study.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/study.py b/study.py index 7013d14..e3044c8 100644 --- a/study.py +++ b/study.py @@ -93,33 +93,6 @@ def study(): sys.exit(0) # Exit gracefully if already completed else: print(incomplete_files) - # Load the state (if available) - # all_results = [] - # for incomplete_file in incomplete_files: - # latest_state = None - # try: - # with open(incomplete_file, 'rb') as f: - # items = [] - # while True: - # try: - # item = pickle.load(f) - # items.append(item) - # except EOFError: - # break - # latest_state = items[-1] # Assuming state is the last item - # except (OSError, pickle.UnpicklingError) as e: - # print(f"Error loading state from {incomplete_file}: {e}") - # if latest_state: - # try: - # # Assuming configuration file is 'smallConf.py' - # config = importlib.import_module("smallConf") - # results = Parallel(config.numJobs)(delayed(runOnce)(config, shape, execID, latest_state) for shape in config.nextShape()) - # all_results.extend(results) # Collect results from all restarts - # except ModuleNotFoundError as e: - # print(f"Error importing configuration file 'smallConf.py': {e}") - # else: - # print(f"No state found for restart from {incomplete_file}. Skipping.") - sys.exit(0) if len(sys.argv) < 2: From c4db8e408e4499f473208d7b0ee94b4a0eb0aa11 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Wed, 27 Mar 2024 11:22:56 +0000 Subject: [PATCH 11/22] store config shape in pickle files Signed-off-by: Arunima Chaudhuri --- DAS/simulator.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/DAS/simulator.py b/DAS/simulator.py index a932e97..8a1867f 100644 --- a/DAS/simulator.py +++ b/DAS/simulator.py @@ -277,6 +277,13 @@ class Simulator: malicious_nodes_not_added_count = 0 steps = 0 unique_run_id = str(uuid.uuid4()) + backup_folder = f"results/{self.execID}/backup" + if not os.path.exists(backup_folder): + os.makedirs(backup_folder) + backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") + + with open(backup_file, 'ab') as f: + pickle.dump(self.shape.__dict__, f) while(True): vectors_data = [] missingVector.append(missingSamples) @@ -374,7 +381,7 @@ class Simulator: 'columnNeighbors': list(self.validators[i].columnNeighbors) } vectors_data.append(validator_data) - + # Alse store for initNetwork vectors_data += (progressVector,missingVector) backup_folder = f"results/{self.execID}/backup" if not os.path.exists(backup_folder): From d591c1724fc5f1aca22480ffa13e105158af23ba Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Wed, 27 Mar 2024 20:38:47 +0000 Subject: [PATCH 12/22] Implement stop and resume functionality Signed-off-by: Arunima Chaudhuri --- DAS/simulator.py | 38 ++------------------------- study.py | 68 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/DAS/simulator.py b/DAS/simulator.py index 8a1867f..947dba7 100644 --- a/DAS/simulator.py +++ b/DAS/simulator.py @@ -281,11 +281,10 @@ class Simulator: if not os.path.exists(backup_folder): os.makedirs(backup_folder) backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") - with open(backup_file, 'ab') as f: pickle.dump(self.shape.__dict__, f) + while(True): - vectors_data = [] missingVector.append(missingSamples) self.logger.debug("Expected Samples: %d" % expected, extra=self.format) self.logger.debug("Missing Samples: %d" % missingSamples, extra=self.format) @@ -362,42 +361,9 @@ class Simulator: self.logger.debug("The entire block is available at step %d, with failure rate %d !" % (steps, self.shape.failureRate), extra=self.format) missingVector.append(missingSamples) break - - for i in range(0, self.shape.numberNodes): - validator_data = { - 'validator_ID': self.validators[i].ID, - 'rowIDs': list(self.validators[i].rowIDs), - 'columnIDs': list(self.validators[i].columnIDs), - 'amImalicious': self.validators[i].amImalicious, - 'amIaddedToQueue': self.validators[i].amIaddedToQueue, - 'msgSentCount': self.validators[i].msgSentCount, - 'msgRecvCount': self.validators[i].msgRecvCount, - 'sampleSentCount': self.validators[i].sampleSentCount, - 'sampleRecvCount': self.validators[i].sampleRecvCount, - 'restoreRowCount': self.validators[i].restoreRowCount, - 'restoreColumnCount': self.validators[i].restoreColumnCount, - 'repairedSampleCount': self.validators[i].repairedSampleCount, - 'rowNeighbors': list(self.validators[i].rowNeighbors), - 'columnNeighbors': list(self.validators[i].columnNeighbors) - } - vectors_data.append(validator_data) - # Alse store for initNetwork - vectors_data += (progressVector,missingVector) - backup_folder = f"results/{self.execID}/backup" - if not os.path.exists(backup_folder): - os.makedirs(backup_folder) - backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") - with open(backup_file, 'ab') as f: - pickle.dump(vectors_data, f) steps += 1 - - backup_folder = f"results/{self.execID}/backup" - if not os.path.exists(backup_folder): - os.makedirs(backup_folder) - backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") - - with open(backup_file, 'ab') as f: # Open in append binary mode + with open(backup_file, 'ab') as f: pickle.dump("completed", f) for i in range(0,self.shape.numberNodes): diff --git a/study.py b/study.py index e3044c8..597f9be 100644 --- a/study.py +++ b/study.py @@ -53,7 +53,9 @@ def check_simulation_completion(state_file): all_completed = True incomplete_files = [] - for filename in sorted(os.listdir(backup_dir), reverse=True): # Iterate in reverse order + completed_files = [] + completed_shapes = [] + for filename in sorted(os.listdir(backup_dir), reverse=True): if not filename.endswith(".pkl"): continue full_path = os.path.join(backup_dir, filename) @@ -63,19 +65,65 @@ def check_simulation_completion(state_file): while True: try: item = pickle.load(f) - items.append(item) # Load all items - except EOFError: # Reached end of file + items.append(item) + except EOFError: break last_item = items[-1] # Access the last item # print(last_item) if last_item != "completed": all_completed = False incomplete_files.append(full_path) + else: + completed_files.append(full_path) + completed_shapes.append(items[0]) except (OSError, pickle.UnpicklingError) as e: print(f"Error loading state from {full_path}: {e}") - all_completed = False # Treat errors as incomplete - break # No need to continue checking other files - return all_completed, incomplete_files + all_completed = False + break + return all_completed, incomplete_files, completed_files, completed_shapes + + +def start_simulation(execID, completed_files, completed_shapes, incomplete_files): + config = importlib.import_module("smallConf") + logger = initLogger(config) + format = {"entity": "Study"} + + results = [] + if not os.path.exists("results"): + os.makedirs("results") + dir = "results/"+execID + if not os.path.exists(dir): + os.makedirs(dir) + if config.saveGit: + with open(dir+"/git.diff", 'w') as f: + subprocess.run(["git", "diff"], stdout=f) + with open(dir+"/git.describe", 'w') as f: + subprocess.run(["git", "describe", "--always"], stdout=f) + subprocess.run(["cp", sys.argv[1], dir+"/"]) + + logger.info("Starting simulations:", extra=format) + start = time.time() + for shape in config.nextShape(): + comparison_dict = shape.__dict__.copy() + ignore_keys = ['randomSeed'] + for key in ignore_keys: + del comparison_dict[key] + + if any(all(comparison_dict[key] == completed_shape[key] for key in comparison_dict.keys() if key not in ignore_keys) for completed_shape in completed_shapes): + print(f"Skipping simulation for shape: {shape.__dict__} (already completed)") + else: + results.append(delayed(runOnce)(config, shape, execID)) + + results = Parallel(config.numJobs)(results) + end = time.time() + logger.info("A total of %d simulations ran in %d seconds" % (len(results), end-start), extra=format) + + if config.visualization: + vis = Visualizer(execID, config) + vis.plotHeatmaps() + + visual = Visualizor(execID, config, results) + visual.plotHeatmaps("nn", "fr") def study(): @@ -87,12 +135,14 @@ def study(): if restart_path: execID = restart_path.split("/")[1] state_file = f"results/{execID}/backup" - all_completed, incomplete_files = check_simulation_completion(state_file) + all_completed, incomplete_files, completed_files, completed_shapes = check_simulation_completion(state_file) + print(completed_shapes) if all_completed: print("Simulation is already completed.") - sys.exit(0) # Exit gracefully if already completed + sys.exit(0) else: - print(incomplete_files) + print("Restarting simulations.") + start_simulation(execID, completed_files, completed_shapes, incomplete_files) sys.exit(0) if len(sys.argv) < 2: From 2aa0074163500684b5d61a914eaf3e5408b1da35 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Thu, 28 Mar 2024 08:59:39 +0000 Subject: [PATCH 13/22] Removed debug prints Signed-off-by: Arunima Chaudhuri --- study.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/study.py b/study.py index 597f9be..1a955d8 100644 --- a/study.py +++ b/study.py @@ -68,8 +68,7 @@ def check_simulation_completion(state_file): items.append(item) except EOFError: break - last_item = items[-1] # Access the last item - # print(last_item) + last_item = items[-1] if last_item != "completed": all_completed = False incomplete_files.append(full_path) @@ -110,7 +109,7 @@ def start_simulation(execID, completed_files, completed_shapes, incomplete_files del comparison_dict[key] if any(all(comparison_dict[key] == completed_shape[key] for key in comparison_dict.keys() if key not in ignore_keys) for completed_shape in completed_shapes): - print(f"Skipping simulation for shape: {shape.__dict__} (already completed)") + logger.info("Skipping simulation for shape (already completed): %s" % (str(shape.__dict__)), extra=format) else: results.append(delayed(runOnce)(config, shape, execID)) @@ -136,7 +135,6 @@ def study(): execID = restart_path.split("/")[1] state_file = f"results/{execID}/backup" all_completed, incomplete_files, completed_files, completed_shapes = check_simulation_completion(state_file) - print(completed_shapes) if all_completed: print("Simulation is already completed.") sys.exit(0) From 04004ed1fb520592687258dc6240d2f642f1deff Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Fri, 29 Mar 2024 21:49:57 +0000 Subject: [PATCH 14/22] make the changes on study level Signed-off-by: Arunima Chaudhuri --- DAS/simulator.py | 12 ------------ study.py | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/DAS/simulator.py b/DAS/simulator.py index 947dba7..3657b03 100644 --- a/DAS/simulator.py +++ b/DAS/simulator.py @@ -9,9 +9,6 @@ from DAS.tools import * from DAS.results import * from DAS.observer import * from DAS.node import * -import os -import pickle -import uuid class Simulator: """This class implements the main DAS simulator.""" @@ -276,13 +273,6 @@ class Simulator: trafficStatsVector = [] malicious_nodes_not_added_count = 0 steps = 0 - unique_run_id = str(uuid.uuid4()) - backup_folder = f"results/{self.execID}/backup" - if not os.path.exists(backup_folder): - os.makedirs(backup_folder) - backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") - with open(backup_file, 'ab') as f: - pickle.dump(self.shape.__dict__, f) while(True): missingVector.append(missingSamples) @@ -363,8 +353,6 @@ class Simulator: break steps += 1 - with open(backup_file, 'ab') as f: - pickle.dump("completed", f) for i in range(0,self.shape.numberNodes): if not self.validators[i].amIaddedToQueue : diff --git a/study.py b/study.py index 1a955d8..bc71add 100644 --- a/study.py +++ b/study.py @@ -5,6 +5,9 @@ import importlib import subprocess from joblib import Parallel, delayed from DAS import * +import os +import pickle +import uuid # Parallel execution: # The code currently uses 'joblib' to execute on multiple cores. For other options such as 'ray', see @@ -29,6 +32,14 @@ def runOnce(config, shape, execID): shape.setSeed(config.randomSeed+"-"+str(shape)) random.seed(shape.randomSeed) + unique_run_id = str(uuid.uuid4()) + backup_folder = f"results/{execID}/backup" + if not os.path.exists(backup_folder): + os.makedirs(backup_folder) + backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") + with open(backup_file, 'ab') as f: + pickle.dump(shape.__dict__, f) + sim = Simulator(shape, config, execID) sim.initLogger() sim.initValidators() @@ -43,6 +54,9 @@ def runOnce(config, shape, execID): visual = Visualizor(execID, config, [result]) visual.plotAll() + with open(backup_file, 'ab') as f: + pickle.dump("completed", f) + return result @@ -98,7 +112,6 @@ def start_simulation(execID, completed_files, completed_shapes, incomplete_files subprocess.run(["git", "diff"], stdout=f) with open(dir+"/git.describe", 'w') as f: subprocess.run(["git", "describe", "--always"], stdout=f) - subprocess.run(["cp", sys.argv[1], dir+"/"]) logger.info("Starting simulations:", extra=format) start = time.time() From 4ad181c91d3cc977bb82073d99f359269483a56c Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Mon, 13 May 2024 16:14:14 +0000 Subject: [PATCH 15/22] use shape for naming pickle files for restarting simulations Signed-off-by: Arunima Chaudhuri --- study.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/study.py b/study.py index bc71add..6776e90 100644 --- a/study.py +++ b/study.py @@ -32,11 +32,10 @@ def runOnce(config, shape, execID): shape.setSeed(config.randomSeed+"-"+str(shape)) random.seed(shape.randomSeed) - unique_run_id = str(uuid.uuid4()) backup_folder = f"results/{execID}/backup" if not os.path.exists(backup_folder): os.makedirs(backup_folder) - backup_file = os.path.join(backup_folder, f"simulation_data_{unique_run_id}.pkl") + backup_file = os.path.join(backup_folder, f"simulation_data_{shape}.pkl") with open(backup_file, 'ab') as f: pickle.dump(shape.__dict__, f) From 1935fafe19cca4a3e520edb0fb625dce17cdd9a2 Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Tue, 14 May 2024 06:45:54 +0000 Subject: [PATCH 16/22] Fixed simulation completion check Signed-off-by: Arunima Chaudhuri --- study.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/study.py b/study.py index 6776e90..7ad33b5 100644 --- a/study.py +++ b/study.py @@ -147,7 +147,23 @@ def study(): execID = restart_path.split("/")[1] state_file = f"results/{execID}/backup" all_completed, incomplete_files, completed_files, completed_shapes = check_simulation_completion(state_file) - if all_completed: + + current_shapes = [] + config = importlib.import_module("smallConf") + + completed_shapes_without_seed = completed_shapes + for shape in config.nextShape(): + shape_dict = copy.deepcopy(shape.__dict__) + del shape_dict['randomSeed'] + current_shapes.append(shape_dict) + for shape in completed_shapes_without_seed: + if 'randomSeed' in shape: + del shape['randomSeed'] + + completed_set = {frozenset(shape.items()) for shape in completed_shapes_without_seed} + current_set = {frozenset(shape.items()) for shape in current_shapes} + + if all_completed and completed_set == current_set: print("Simulation is already completed.") sys.exit(0) else: From 732589185cd9b4aab529fa5cb2445c1472f82759 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Wed, 15 May 2024 13:19:03 +0000 Subject: [PATCH 17/22] Creating separate plots for each varying params --- DAS/visualizor.py | 225 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 175 insertions(+), 50 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 8ffb331..9778a2f 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1069,68 +1069,193 @@ class Visualizor: plt.xlabel(conf['xlabel']) plt.ylabel(conf['ylabel']) plt.title(conf['title']) - plt.savefig(f"results/{self.execID}/heatmaps/{conf['path']}") + folder = f"results/{self.execID}/heatmaps/{conf['folder']}" + os.makedirs(folder, exist_ok=True) + plt.savefig(f"{folder}/{conf['path']}") plt.clf() # x -> network degree, y -> number of nodes, weights -> simulation duration def plotNWDegVsNodeOnRuntime(self): - x = [result.shape.netDegree for result in self.results] - y = [result.shape.numberNodes for result in self.results] - weights = [self.config.stepDuration * (len(result.missingVector) - 1) for result in self.results] - - if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + xyS = dict() + for result in self.results: + attrbs = self.__get_attrbs__(result) + textBox = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ + +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ + +"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"\ + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']\ + +"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + filename = "bsrn_" + attrbs['bsrn'] +\ + "_bsrk_" + attrbs['bsrk'] +\ + "_bscn_" + attrbs['bscn' ] +\ + "_bsck_" + attrbs['bsck'] +\ + "_fr_" + attrbs['fr'] +\ + "_mn_" + attrbs['mn'] +\ + "_cusr_" + attrbs['cusr'] +\ + "_cusc_" + attrbs['cusc'] +\ + "_vpn1_" + attrbs['vpn1'] +\ + "_vpn2_" + attrbs['vpn2'] +\ + "_r_" + attrbs['r'] + identifier = ( + attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], + attrbs['bsck'], attrbs['fr'], attrbs['mn'], + attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], + attrbs['vpn2'], attrbs['r'] + ) + if identifier in xyS.keys(): + xyS[identifier]['x'].append(result.shape.netDegree) + xyS[identifier]['y'].append(result.shape.numberNodes) + xyS[identifier]['w'].append(self.config.stepDuration * (len(result.missingVector) - 1)) + else: + xyS[identifier] = { + 'x': [result.shape.netDegree], + 'y': [result.shape.numberNodes], + 'w': [self.config.stepDuration * (len(result.missingVector) - 1)], + 'textBox': textBox, + 'filename': filename + } - conf = { - 'x': x, - 'y': y, - 'weights': weights, - 'xlabel': 'Net Degree', - 'ylabel': 'Number of Nodes', - 'title': 'Net Degree vs. Number of Nodes on Simulation Runtime', - 'path': 'NWDegVsNodeOnRuntime.png' - } - - self.plotHeatMapData(conf) + for v in xyS.values(): + x = v['x'] + y = v['y'] + weights = v['w'] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Number of Nodes', + 'title': 'Net Degree vs. Number of Nodes on Simulation Runtime (ms)', + 'folder': 'NWDegVsNodeOnRuntime', + 'textBox': v['textBox'], + 'path': f"{v['filename']}.png" + } + + self.plotHeatMapData(conf) # x -> network degree, y -> % of malicious nodes, weights -> no of missing samples def plotNWDegVsMalNodeOnMissingSamples(self): - x = [result.shape.netDegree for result in self.results] - y = [result.shape.maliciousNodes for result in self.results] - weights = [result.missingVector[-1] for result in self.results] - - if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + xyS = dict() + for result in self.results: + attrbs = self.__get_attrbs__(result) + textBox = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ + +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ + +"\nFailure rate: "+attrbs['fr']+"%"+"\nNodes: "+attrbs['nn']\ + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']\ + +"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + filename = "bsrn_" + attrbs['bsrn'] +\ + "_bsrk_" + attrbs['bsrk'] +\ + "_bscn_" + attrbs['bscn' ] +\ + "_bsck_" + attrbs['bsck'] +\ + "-nn-" + attrbs['nn'] +\ + "_fr_" + attrbs['fr'] +\ + "_cusr_" + attrbs['cusr'] +\ + "_cusc_" + attrbs['cusc'] +\ + "_vpn1_" + attrbs['vpn1'] +\ + "_vpn2_" + attrbs['vpn2'] +\ + "_r_" + attrbs['r'] + identifier = ( + attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], + attrbs['bsck'], attrbs['fr'], attrbs['nn'], + attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], + attrbs['vpn2'], attrbs['r'] + ) + if identifier in xyS.keys(): + xyS[identifier]['x'].append(result.shape.netDegree) + xyS[identifier]['y'].append(result.shape.maliciousNodes) + xyS[identifier]['w'].append(result.missingVector[-1]) + else: + xyS[identifier] = { + 'x': [result.shape.netDegree], + 'y': [result.shape.maliciousNodes], + 'w': [result.missingVector[-1]], + 'textBox': textBox, + 'filename': filename + } - conf = { - 'x': x, - 'y': y, - 'weights': weights, - 'xlabel': 'Net Degree', - 'ylabel': 'Malicious Nodes (%)', - 'title': 'Net Degree vs Malicious Nodes (%) on Missing Samples', - 'path': 'NWDegVsMalNodeOnMissingSamples.png' - } - - self.plotHeatMapData(conf) + for v in xyS.values(): + x = v['x'] + y = v['y'] + weights = v['w'] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Malicious Nodes (%)', + 'title': 'Net Degree vs Malicious Nodes (%) on Missing Samples', + 'folder': 'NWDegVsMalNodeOnMissingSamples', + 'textBox': v['textBox'], + 'path': f"{v['filename']}.png" + } + + self.plotHeatMapData(conf) # x -> network degree, y -> failure rate, weights -> no of missing samples def plotNWDegVsFailureRateOnMissingSamples(self): - x = [result.shape.netDegree for result in self.results] - y = [result.shape.failureRate for result in self.results] - weights = [result.missingVector[-1] for result in self.results] - - if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap - - conf = { - 'x': x, - 'y': y, - 'weights': weights, - 'xlabel': 'Net Degree', - 'ylabel': 'Failure Rate (%)', - 'title': 'Net Degree vs Failure Rate (%) on Missing Samples', - 'path': 'NWDegVsFailureRateOnMissingSamples.png' - } - - self.plotHeatMapData(conf) + xyS = dict() + for result in self.results: + attrbs = self.__get_attrbs__(result) + textBox = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ + +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ + +"\nNodes: "+attrbs['nn']+"\nMalicious Node: "+attrbs['mn']+"%"\ + +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']\ + +"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2'] + filename = "bsrn_" + attrbs['bsrn'] +\ + "_bsrk_" + attrbs['bsrk'] +\ + "_bscn_" + attrbs['bscn' ] +\ + "_bsck_" + attrbs['bsck'] +\ + "-nn-" + attrbs['nn'] +\ + "_mn_" + attrbs['mn'] +\ + "_cusr_" + attrbs['cusr'] +\ + "_cusc_" + attrbs['cusc'] +\ + "_vpn1_" + attrbs['vpn1'] +\ + "_vpn2_" + attrbs['vpn2'] +\ + "_r_" + attrbs['r'] + identifier = ( + attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], + attrbs['bsck'], attrbs['mn'], attrbs['nn'], + attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], + attrbs['vpn2'], attrbs['r'] + ) + if identifier in xyS.keys(): + xyS[identifier]['x'].append(result.shape.netDegree) + xyS[identifier]['y'].append(result.shape.failureRate) + xyS[identifier]['w'].append(result.missingVector[-1]) + else: + xyS[identifier] = { + 'x': [result.shape.netDegree], + 'y': [result.shape.failureRate], + 'w': [result.missingVector[-1]], + 'textBox': textBox, + 'filename': filename + } + + for v in xyS.values(): + x = v['x'] + y = v['y'] + weights = v['w'] + + if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap + + conf = { + 'x': x, + 'y': y, + 'weights': weights, + 'xlabel': 'Net Degree', + 'ylabel': 'Failure Rate (%)', + 'title': 'Net Degree vs Failure Rate (%) on Missing Samples', + 'folder': 'NWDegVsFailureRateOnMissingSamples', + 'textBox': v['textBox'], + 'path': f"{v['filename']}.png" + } + + self.plotHeatMapData(conf) def plotAllHeatMaps(self): self.plotNWDegVsNodeOnRuntime() From 7dfc0c099c83da142c9c0a4c0ab7362960c2e3d0 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Thu, 16 May 2024 05:09:13 +0000 Subject: [PATCH 18/22] Added textbox in heatmap plots --- DAS/visualizor.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 9778a2f..7372b68 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1065,14 +1065,26 @@ class Visualizor: data = {'x': conf['x'], 'y': conf['y'], 'weights': conf['weights']} df = pd.DataFrame(data) pivot_df = df.pivot_table(index='y', columns='x', values='weights', aggfunc="sum") - sns.heatmap(pivot_df, annot=True, cmap='viridis', fmt='.0f') - plt.xlabel(conf['xlabel']) - plt.ylabel(conf['ylabel']) - plt.title(conf['title']) + + # Create subplots + fig, (ax_heatmap, ax_textbox) = plt.subplots(1, 2, figsize=(18, 6)) + + # Plot heatmap + sns.heatmap(pivot_df, annot=True, cmap='viridis', fmt='.0f', ax=ax_heatmap) + ax_heatmap.set_xlabel(conf['xlabel']) + ax_heatmap.set_ylabel(conf['ylabel']) + ax_heatmap.set_title(conf['title']) + + # Plot textbox + props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) + ax_textbox.text(0.5, 0.5, conf["textBox"], fontsize=14, verticalalignment='center', transform=ax_textbox.transAxes, bbox=props) + ax_textbox.axis('off') # Turn off axis for the textbox subplot + folder = f"results/{self.execID}/heatmaps/{conf['folder']}" os.makedirs(folder, exist_ok=True) plt.savefig(f"{folder}/{conf['path']}") plt.clf() + plt.close() # x -> network degree, y -> number of nodes, weights -> simulation duration def plotNWDegVsNodeOnRuntime(self): From 804fdcdee3259b57e17ea11ac1921ee9b3f8f97f Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Thu, 16 May 2024 05:13:24 +0000 Subject: [PATCH 19/22] fixed old heatmap bug --- DAS/visualizer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/DAS/visualizer.py b/DAS/visualizer.py index 34da38c..00459d1 100644 --- a/DAS/visualizer.py +++ b/DAS/visualizer.py @@ -182,6 +182,7 @@ class Visualizer: """Average the runs if needed""" if(len(self.config.runs) > 1): data = self.averageRuns(data, len(self.config.runs)) + else: return filteredKeys = self.similarKeys(data) vmin, vmax = 0, self.maxTTA+1000 print("Plotting heatmaps...") From 299323f655c1c4a15627970cdb5a7ab3075fd547 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Thu, 16 May 2024 06:07:40 +0000 Subject: [PATCH 20/22] Adding missing sample count in missing samples plot textbox --- DAS/visualizor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 7372b68..fd3ae0a 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -761,7 +761,8 @@ class Visualizor: +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ - +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Sample: "+str(min(result.missingVector) * 100 / max(result.missingVector))+"%" + +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Sample: "+str(min(result.missingVector) * 100 / max(result.missingVector))+"%"\ + +"\nMissing Samples: "+str(result.missingVector[-1]) conf["title"] = "Missing Samples" conf["type"] = "plot_with_1line" conf["legLoc"] = 1 From c770dfd25d3364ee720319a02c3afc5734c04968 Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Thu, 16 May 2024 12:14:31 +0000 Subject: [PATCH 21/22] Missing Samples renamed to Missing Segments --- DAS/visualizor.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index fd3ae0a..3e38934 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -121,7 +121,7 @@ class Visualizor: for result in self.results: plotPath = "results/"+self.execID+"/plots/"+str(result.shape) os.makedirs(plotPath, exist_ok=True) - self.plotMissingSamples(result, plotPath) + self.plotMissingSegments(result, plotPath) self.plotProgress(result, plotPath) self.plotSentData(result, plotPath) self.plotRecvData(result, plotPath) @@ -753,27 +753,27 @@ class Visualizor: plotBoxData(conf) print("Plot %s created." % conf["path"]) - def plotMissingSamples(self, result, plotPath): - """Plots the missing samples in the network""" + def plotMissingSegments(self, result, plotPath): + """Plots the missing segments in the network""" conf = {} attrbs = self.__get_attrbs__(result) conf["textBox"] = "Row Size (N, K): "+attrbs['bsrn']+ ", "+attrbs['bsrk']\ +"\nColumn Size: (N, K): "+attrbs['bscn']+ ", "+attrbs['bsck']\ +"\nNumber of nodes: "+attrbs['nn']+"\nFailure rate: "+attrbs['fr']+"%"+"\nMalicious Node: "+attrbs['mn']+"%"+"\nNetwork degree: "+attrbs['nd']\ +"\nCustody Rows: "+attrbs['cusr']+"\nCustody Cols: "+attrbs['cusc']+"\nCustody 1: "+attrbs['vpn1']+"\nCustody 2: "+attrbs['vpn2']\ - +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Sample: "+str(min(result.missingVector) * 100 / max(result.missingVector))+"%"\ - +"\nMissing Samples: "+str(result.missingVector[-1]) - conf["title"] = "Missing Samples" + +"\nSegment Size: "+str(self.config.segmentSize)+"\nMissing Segment: "+str(round(min(result.missingVector) * 100 / max(result.missingVector), 3))+"%"\ + +"\nMissing Segments: "+str(result.missingVector[-1]) + conf["title"] = "Missing Segments" conf["type"] = "plot_with_1line" conf["legLoc"] = 1 conf["desLoc"] = 1 conf["colors"] = ["m-"] - conf["labels"] = ["Missing Samples"] + conf["labels"] = ["Missing Segments"] conf["xlabel"] = "Time (ms)" - conf["ylabel"] = "Number of Missing Samples" + conf["ylabel"] = "Number of Missing Segments" conf["data"] = [result.missingVector] conf["xdots"] = [x*self.config.stepDuration for x in range(len(result.missingVector))] - conf["path"] = plotPath+"/missingSamples.png" + conf["path"] = plotPath+"/missingSegments.png" maxi = 0 for v in conf["data"]: if max(v) > maxi: @@ -781,7 +781,7 @@ class Visualizor: conf["yaxismax"] = maxi x = result.shape.nbCols * result.shape.custodyRows + result.shape.nbRows * result.shape.custodyCols conf["expected_value"] = (result.shape.numberNodes - 1) * (result.shape.class1ratio * result.shape.vpn1 * x + (1 - result.shape.class1ratio) * result.shape.vpn2 * x) - conf["line_label"] = "Total samples to deliver" + conf["line_label"] = "Total segments to deliver" plotData(conf) print("Plot %s created." % conf["path"]) From e5b4037bda2f14c2952638967b6b5e2ddc151b8e Mon Sep 17 00:00:00 2001 From: Sudipta Basak Date: Thu, 16 May 2024 12:42:17 +0000 Subject: [PATCH 22/22] Average of all runs considered for heatmaps --- DAS/visualizor.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/DAS/visualizor.py b/DAS/visualizor.py index 3e38934..9cd2860 100644 --- a/DAS/visualizor.py +++ b/DAS/visualizor.py @@ -1087,6 +1087,15 @@ class Visualizor: plt.clf() plt.close() + # Number of simulation runs with the same parameters for statistical relevance + def totalRuns(self): + rs = [] + for result in self.results: + attrbs = self.__get_attrbs__(result) + rs.append(int(attrbs['r'])) + + return max(rs) - min(rs) + 1 + # x -> network degree, y -> number of nodes, weights -> simulation duration def plotNWDegVsNodeOnRuntime(self): xyS = dict() @@ -1106,13 +1115,12 @@ class Visualizor: "_cusr_" + attrbs['cusr'] +\ "_cusc_" + attrbs['cusc'] +\ "_vpn1_" + attrbs['vpn1'] +\ - "_vpn2_" + attrbs['vpn2'] +\ - "_r_" + attrbs['r'] + "_vpn2_" + attrbs['vpn2'] identifier = ( attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], attrbs['bsck'], attrbs['fr'], attrbs['mn'], attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], - attrbs['vpn2'], attrbs['r'] + attrbs['vpn2'] ) if identifier in xyS.keys(): xyS[identifier]['x'].append(result.shape.netDegree) @@ -1127,10 +1135,11 @@ class Visualizor: 'filename': filename } + runs = self.totalRuns() for v in xyS.values(): x = v['x'] y = v['y'] - weights = v['w'] + weights = [(w / runs) for w in v['w']] if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap @@ -1167,13 +1176,12 @@ class Visualizor: "_cusr_" + attrbs['cusr'] +\ "_cusc_" + attrbs['cusc'] +\ "_vpn1_" + attrbs['vpn1'] +\ - "_vpn2_" + attrbs['vpn2'] +\ - "_r_" + attrbs['r'] + "_vpn2_" + attrbs['vpn2'] identifier = ( attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], attrbs['bsck'], attrbs['fr'], attrbs['nn'], attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], - attrbs['vpn2'], attrbs['r'] + attrbs['vpn2'] ) if identifier in xyS.keys(): xyS[identifier]['x'].append(result.shape.netDegree) @@ -1188,10 +1196,11 @@ class Visualizor: 'filename': filename } + runs = self.totalRuns() for v in xyS.values(): x = v['x'] y = v['y'] - weights = v['w'] + weights = [(w / runs) for w in v['w']] if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap @@ -1228,13 +1237,12 @@ class Visualizor: "_cusr_" + attrbs['cusr'] +\ "_cusc_" + attrbs['cusc'] +\ "_vpn1_" + attrbs['vpn1'] +\ - "_vpn2_" + attrbs['vpn2'] +\ - "_r_" + attrbs['r'] + "_vpn2_" + attrbs['vpn2'] identifier = ( attrbs['bsrn'], attrbs['bsrk'], attrbs['bscn'], attrbs['bsck'], attrbs['mn'], attrbs['nn'], attrbs['cusr'], attrbs['cusc'], attrbs['vpn1'], - attrbs['vpn2'], attrbs['r'] + attrbs['vpn2'] ) if identifier in xyS.keys(): xyS[identifier]['x'].append(result.shape.netDegree) @@ -1249,10 +1257,11 @@ class Visualizor: 'filename': filename } + runs = self.totalRuns() for v in xyS.values(): x = v['x'] y = v['y'] - weights = v['w'] + weights = [(w / runs) for w in v['w']] if len(set(x)) * len(set(y)) < 2: return # Not enough unique params for heatmap