def __init__(self, name=None): GraphWidget.__init__(self) if name is not None: self._name = name ActiveTraceObserver.__init__(self) self.params.addChildren([ {'name':'Redraw after Each', 'type':'bool', 'value':False}, {'name':'Trace Range', 'key':'tracerng', 'type':'range', 'limits':(0, 0), 'value':(0, 0)}, {'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'limits':(0, 0), 'value':(0, 0), 'graphwidget':self}, {'name':'Downsampling Mode', 'key':'dsmode', 'type':'list', 'values':{'None':None, 'Subsample':'subsample', 'Mean':'mean', 'Peak':'peak'}, 'value':'peak', 'action':self.plotInputTrace}, {'name':'Y Axis', 'type':'group', 'expanded':False, 'children':[ {'name':'Unity', 'type':'list', 'values':{"None":"", "Voltage":"V", "Current":"A"}, 'value':"", 'action':self.plotInputTrace}, {'name':'Scale Factor', 'type':'float', 'limits':(1E-9, 1E9), 'value':1.0, 'action':self.plotInputTrace}, {'name':'Offset Factor', 'type':'float', 'limits':(-1E9, 1E9), 'value':0.0, 'action':self.plotInputTrace}, ]}, {'name':'X Axis', 'type':'list', 'values':{"Sample":"Pts.", "Time":"s"}, 'value':"Pts.", 'action':self.plotInputTrace}, {'name':'Redraw', 'type':'action', 'action':self.plotInputTrace}, ]) self.findParam('input').setValue(TraceSource.registeredObjects["Trace Management"]) TraceSource.sigRegisteredObjectsChanged.connect(self.traceSourcesChanged) self.resetTraceLimits() self.setDefaultYRange(-0.5, 0.5) self.YDefault()
def __init__(self, name=None): GraphWidget.__init__(self) self.getParams().addChildren([ {'name':'Draw Type', 'type':'list', 'key':'drawtype', 'values':['Fastest', 'Normal', 'Detailed'], 'value':'Normal', 'help': '%namehdr%'+ "Draw types:\n" " * Fast: Group traces into a min/max area;\n" " * Normal: Plot all traces continuously;\n" " * Detailed: Plot all traces individually.\n\n" "Only highlighted traces can be selected in fast/normal modes.\n" }, ]) self.setObjectName(self.getName()) self.bselection = QToolBar() self.layout().addWidget(self.bselection) self.doRedraw = True self.enabledbytes = [] AttackObserver.__init__(self) self.initUI(True) # Setup the redrawPlot() to be delayed when pressing the Key buttons self.delayedRedrawPlot = Timer() self.delayedRedrawPlot.timeout.connect(self.redrawPlot) self.delayedRedrawPlot.setSingleShot(True) self.delayedRedrawPlot.setInterval(1000)
def __init__(self, name=None): GraphWidget.__init__(self) if name is not None: self._name = name ActiveTraceObserver.__init__(self) self.params.addChildren([ {'name':'Redraw after Each', 'type':'bool', 'value':False}, {'name':'Trace Range', 'key':'tracerng', 'type':'range', 'limits':(0, 0), 'value':(0, 0)}, {'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'limits':(0, 0), 'value':(0, 0), 'graphwidget':self}, {'name':'Y Axis', 'type':'group', 'expanded':False, 'children':[ {'name':'Unity', 'type':'list', 'values':{"None":"", "Voltage":"V", "Current":"A"}, 'value':"", 'action':self.plotInputTrace}, {'name':'Scale Factor', 'type':'float', 'limits':(1E-9, 1E9), 'value':1.0, 'action':self.plotInputTrace}, {'name':'Offset Factor', 'type':'float', 'limits':(-1E9, 1E9), 'value':0.0, 'action':self.plotInputTrace}, ]}, {'name':'X Axis', 'type':'list', 'values':{"Sample":"Pts.", "Time":"s"}, 'value':"Pts.", 'action':self.plotInputTrace}, {'name':'Redraw', 'type':'action', 'action':self.plotInputTrace}, ]) self.findParam('input').setValue(TraceSource.registeredObjects["Trace Management"]) TraceSource.sigRegisteredObjectsChanged.connect(self.traceSourcesChanged) self.resetTraceLimits() self.setDefaultYRange(-0.5, 0.5) self.YDefault()
def __init__(self, name=None): GraphWidget.__init__(self) if name is not None: self._name = name self.getParams().addChildren([ {'name':'Symbol', 'type':'list', 'values':['o', 's', 't', 'd', '+'], 'value':'o'}, ]) self.setDefaultYRange(-0.5, 0.5)
def __init__(self, name=None): GraphWidget.__init__(self) if name is not None: self._name = name self.getParams().addChildren([ { 'name': 'Symbol', 'type': 'list', 'values': ['o', 's', 't', 'd', '+'], 'value': 'o' }, ]) self.setDefaultYRange(-0.5, 0.5)
def __init__(self, parentParam=None, name=None): GraphWidget.__init__(self) if name is not None: self._name = name ActiveTraceObserver.__init__(self) self.params.addChildren([ {'name':'Redraw after Each', 'type':'bool', 'value':False}, {'name':'Trace Range', 'key':'tracerng', 'type':'range', 'limits':(0, 0), 'value':(0, 0)}, {'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'limits':(0, 0), 'value':(0, 0), 'graphwidget':self}, {'name':'Redraw', 'type':'action', 'action':lambda _: self.plotInputTrace()}, ]) self.findParam('input').setValue(TraceSource.registeredObjects["Trace Management"]) TraceSource.sigRegisteredObjectsChanged.connect(self.traceSourcesChanged) self.resetTraceLimits() self.setDefaultYRange(-0.5, 0.5) self.YDefault()
def __init__(self, parent): AutoScript.__init__(self) self._autoscript_init = False self.parent = parent self.poi = POI(self) self.poiDock = CWMainGUI.getInstance().addDock( self.poi, "Partition Comparison POI Table", area=Qt.TopDockWidgetArea) self.poiDock.hide() self.defineName() self._traces = None self.api = CWCoreAPI.getInstance() self.graph = GraphWidget() self.bselection = QToolBar() self.graph.addWidget(self.bselection) self.graphDock = CWMainGUI.getInstance().addDock( self.graph, "Partition Comparison Graph", area=Qt.TopDockWidgetArea) self.graphDock.hide()
def __init__(self, name=None): GraphWidget.__init__(self) self.getParams().addChildren([ { 'name': 'Draw Type', 'type': 'list', 'key': 'drawtype', 'values': ['Fastest', 'Normal', 'Detailed'], 'value': 'Normal', 'help': '%namehdr%' + "Draw types:\n" " * Fast: Group traces into a min/max area;\n" " * Normal: Plot all traces continuously;\n" " * Detailed: Plot all traces individually.\n\n" "Only highlighted traces can be selected in fast/normal modes.\n" }, ]) self.setObjectName(self.getName()) self.bselection = QToolBar() self.layout().addWidget(self.bselection) self.doRedraw = True self.enabledbytes = [] AttackObserver.__init__(self) self.initUI(True) # Setup the redrawPlot() to be delayed when pressing the Key buttons self.delayedRedrawPlot = Timer() self.delayedRedrawPlot.timeout.connect(self.redrawPlot) self.delayedRedrawPlot.setSingleShot(True) self.delayedRedrawPlot.setInterval(1000)
def __init__(self, parent): AutoScript.__init__(self) self._autoscript_init = False self.parent = parent self.poi = POI(self) self.poiDock = CWMainGUI.getInstance().addDock(self.poi, "Partition Comparison POI Table", area=Qt.TopDockWidgetArea) self.poiDock.hide() self.defineName() self._traces = None self.api = CWCoreAPI.getInstance() self.graph = GraphWidget() self.bselection = QToolBar() self.graph.addWidget(self.bselection) self.graphDock = CWMainGUI.getInstance().addDock(self.graph, "Partition Comparison Graph", area=Qt.TopDockWidgetArea) self.graphDock.hide()
class PartitionDisplay(Parameterized, AutoScript): _name = "Partition Comparison" def __init__(self, parent): AutoScript.__init__(self) self._autoscript_init = False self.parent = parent self.poi = POI(self) self.poiDock = CWMainGUI.getInstance().addDock( self.poi, "Partition Comparison POI Table", area=Qt.TopDockWidgetArea) self.poiDock.hide() self.defineName() self._traces = None self.api = CWCoreAPI.getInstance() self.graph = GraphWidget() self.bselection = QToolBar() self.graph.addWidget(self.bselection) self.graphDock = CWMainGUI.getInstance().addDock( self.graph, "Partition Comparison Graph", area=Qt.TopDockWidgetArea) self.graphDock.hide() def defineName(self): self.partObject = Partition() partModeList = {} for a in self.partObject.supportedMethods: partModeList[a.partitionType] = a self.diffObject = DifferenceMode() diffModeList = {} for a in self.diffObject.supportedMethods: diffModeList[a.differenceType] = a self.addGroup("generatePartitions") self.addGroup("generatePartitionStats") self.addGroup("generatePartitionDiffs") self.addGroup("displayPartitionDiffs") self.getParams().addChildren([ { 'name': 'Comparison Mode', 'key': 'diffmode', 'type': 'list', 'values': diffModeList, 'value': self.diffObject.diffMethodClass, 'action': lambda _: self.updateScript() }, { 'name': 'Partition Mode', 'key': 'partmode', 'type': 'list', 'values': partModeList, 'value': self.partObject.partMethodClass, 'action': lambda _: self.updateScript() }, { 'name': 'Display', 'type': 'action', 'action': lambda _: self.runAction() }, { 'name': 'Auto-Save Data to Project', 'key': 'part-saveints', 'type': 'bool', 'value': False, 'action': lambda _: self.updateScript() }, { 'name': 'Auto-Load Data from Project', 'key': 'part-loadints', 'type': 'bool', 'value': False, 'action': lambda _: self.updateScript() }, { 'name': 'Points of Interest', 'key': 'poi', 'type': 'group', 'children': [ { 'name': 'Selection Mode', 'type': 'list', 'values': { 'Max N Points/Subkey': 'maxn' }, 'value': 'maxn' }, { 'name': 'Point Range', 'key': 'poi-pointrng', 'type': 'range', 'limits': (0, 0), 'default': (0, 0), 'value': (0, 0), 'action': lambda _: self.updatePOI() }, { 'name': 'Num POI/Subkey', 'key': 'poi-nummax', 'type': 'int', 'limits': (1, 200), 'value': 1, 'action': lambda _: self.updatePOI() }, { 'name': 'Min Spacing between POI', 'key': 'poi-minspace', 'type': 'int', 'limits': (1, 100E6), 'value': 1, 'step': 100, 'action': lambda _: self.updatePOI() }, { 'name': 'Hill detection', 'key': 'poi-hilldet', 'type': 'bool', 'value': True, 'tip': "Extend the bounds downhill for each peak", 'action': lambda _: self.updatePOI() }, # {'name':'Threshold', 'key':'threshold', 'type':'int', 'visible':False}, { 'name': 'Open POI Table', 'type': 'action', 'action': lambda _: self.poiDock.show() }, ] }, ]) def updatePOI(self, _=None): self.updateScript() if self._autoscript_init == False: return # Some sort of race condition - applying Therac-25 type engineering and just # randomly hope this is enough delay QTimer.singleShot( 500, lambda: self.runScriptFunction.emit( "TraceExplorerDialog_PartitionDisplay_findPOI")) def setBytePlot(self, num, sel): self.enabledbytes[num] = sel if self.doRedraw: self.redrawPlot() def setByteAll(self, status): self.doRedraw = False for i, t in enumerate(self.byteNumAct): t.defaultWidget().setChecked(status) self.setBytePlot(i, status) self.doRedraw = True self.redrawPlot() def redrawPlot(self): self.graph.clearPushed() for bnum in range(0, self.numKeys): if self.enabledbytes[bnum]: self.graph.setColorInt(bnum, self.numKeys) self.graph.passTrace(self.SADList[bnum], pen=pg.mkPen(pg.intColor(bnum, 16)), idString=str(bnum)) def updateScript(self, ignored=None): ##Partitioning & Differences try: diffMethodStr = self.findParam('diffmode').getValue().__name__ partMethodStr = self.findParam('partmode').getValue().__name__ except AttributeError as e: return self.importsAppend( 'from chipwhisperer.analyzer.utils.Partition import PartitionRandDebug, PartitionRandvsFixed, PartitionEncKey, PartitionHWIntermediate, PartitionHDLastRound' ) self.importsAppend( 'from chipwhisperer.analyzer.utils.TraceExplorerScripts.PartitionDisplay import DifferenceModeTTest, DifferenceModeSAD' ) self.importsAppend( 'from chipwhisperer.analyzer.ui.CWAnalyzerGUI import CWAnalyzerGUI' ) self.addGroup("displayPartitionStats") self.addVariable('displayPartitionStats', 'ted', 'self.') self.addFunction('displayPartitionStats', 'setTraceSource', 'UserScript.traces', obj='ted') self.addFunction('displayPartitionStats', 'parent.getProgressIndicator', '', 'progressBar', obj='ted') self.addFunction('displayPartitionStats', 'partObject.setPartMethod', partMethodStr, obj='ted') self.addFunction('displayPartitionStats', 'partObject.generatePartitions', 'saveFile=True, loadFile=False', 'partData', obj='ted') self.addFunction( 'displayPartitionStats', 'generatePartitionStats', 'partitionData={"partclass":%s, "partdata":partData}, saveFile=True, progressBar=progressBar' % partMethodStr, 'partStats', obj='ted') self.addFunction( 'displayPartitionStats', 'generatePartitionDiffs', '%s, statsInfo={"partclass":%s, "stats":partStats}, saveFile=True, loadFile=False, progressBar=progressBar' % (diffMethodStr, partMethodStr), 'partDiffs', obj='ted') self.addFunction('displayPartitionStats', 'displayPartitions', 'differences={"partclass":%s, "diffs":partDiffs}' % partMethodStr, obj='ted') self.addFunction('displayPartitionStats', 'poi.setDifferences', 'partDiffs', obj='ted') ##Points of Interest ptrng = self.findParam(["Points of Interest", 'poi-pointrng']).getValue() self.addGroup("findPOI") self.addVariable('findPOI', 'ted', 'self.') self.addFunction( 'findPOI', 'poi.calcPOI', 'numMax=%d, pointRange=(%d, %d), minSpace=%d' % (self.findParam(["Points of Interest", 'poi-nummax' ]).getValue(), ptrng[0], ptrng[1], self.findParam(["Points of Interest", 'poi-minspace' ]).getValue()), obj='ted') #Check if this updateScript was called as a result of showing the TraceExplorer window if ignored == "traceexplorer_show": self._autoscript_init = True def generatePartitionStats(self, partitionData={ "partclass": None, "partdata": None }, saveFile=False, loadFile=False, tRange=(0, -1), progressBar=None): traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(partitionData["partclass"]) self.numKeys = len( self.partObject.partMethod.getPartitionNum(traces, 0)) numPoints = traces.numPoints() if loadFile: cfgsecs = self.api.project().getDataConfig( sectionName="Trace Statistics", subsectionName="Total Trace Statistics") foundsecs = [] for cfg in cfgsecs: desiredsettings = {} desiredsettings["tracestart"] = tRange[0] desiredsettings["traceend"] = tRange[1] desiredsettings[ "partitiontype"] = self.partObject.partMethod.__class__.__name__ if self.api.project().checkDataConfig(cfg, desiredsettings): foundsecs.append(cfg) else: foundsecs = [] if len(foundsecs) > 1: IOError("Too many sections!!!") elif len(foundsecs) == 1: fname = self.api.project().convertDataFilepathAbs( foundsecs[0]["filename"]) stats = np.load(fname) else: # Array to hold average + stddev of all traces/partitions A_k = [] A_j = [] Q_k = [] dataArrays = [A_k, A_j, Q_k] ACnt = [] for bnum in range(0, self.numKeys): for d in dataArrays: d.append([]) ACnt.append([]) for i in range(0, self.partObject.partMethod.getNumPartitions()): for d in dataArrays: d[bnum].append(np.zeros(numPoints)) ACnt[bnum].append(0) # Get segment list segList = traces.getSegmentList() if progressBar: progressBar.setWindowTitle("Phase 1: Trace Statistics") progressBar.setMaximum( bnum) # len(segList['offsetList']) * self.numKeys) progressBar.show() # TODO: Double-check this fix # for tsegn, segtrace in enumerate(segList['offsetList']): tsegn = 0 if progressBar: progressBar.setText("Segment %d" % tsegn) # Average data needs to be calculated # Require partition list partData = partitionData["partdata"] # print "Calculating Average + Std-Dev" # Std-Dev calculation: # A[0] = 0 # A[k] = A[k-1] + (x[k] - A[k-1]) / k # Q[0] = 0 # Q[k] = Q[k-1] + (x[k] - A[k-1])(x[k] - A[k]) for bnum in range(0, self.numKeys): progressBar.updateStatus(tsegn * self.numKeys + bnum) if progressBar.wasAborted(): break for i in range(0, self.partObject.partMethod.getNumPartitions()): util.updateUI() tlist = partData[bnum][i] if len(tlist) > 0: for tnum in tlist: if tnum > tRange[0] and tnum < tRange[1]: t = traces.getTrace(tnum) ACnt[bnum][i] += 1 A_k[bnum][i] = A_k[bnum][i] + ( t - A_j[bnum][i]) / ACnt[bnum][i] Q_k[bnum][i] = Q_k[bnum][i] + ( (t - A_j[bnum][i]) * (t - A_k[bnum][i])) A_j[bnum][i] = A_k[bnum][i] if progressBar.wasAborted(): progressBar.hide() return # Finally get variance for bnum in range(0, self.numKeys): for i in range(0, self.partObject.partMethod.getNumPartitions()): # TODO: Should be using population variance or sample variance (e.g. /n or /n-1)? # Since this is taken over very large sample sizes I imagine it won't matter # ultimately. Q_k[bnum][i] = Q_k[bnum][i] / max(ACnt[bnum][i] - 1, 1) # Average is in A_k stats = {"mean": A_k, "variance": Q_k, "number": ACnt} # Wasn't cancelled - save this to project file for future use if requested if saveFile: progressBar.setText("Saving Mean/Variance Partitions") cfgsec = self.api.project().addDataConfig( sectionName="Trace Statistics", subsectionName="Total Trace Statistics") cfgsec["tracestart"] = tRange[0] cfgsec["traceend"] = tRange[1] cfgsec[ "partitiontype"] = self.partObject.partMethod.__class__.__name__ fname = self.api.project().getDataFilepath( 'tracestats-%s-%d-%s.npz' % (cfgsec["partitiontype"], tRange[0], tRange[1]), 'analysis') # Save mean/variance for trace np.savez(fname["abs"], mean=A_k, variance=Q_k, number=ACnt) cfgsec["filename"] = fname["rel"] progressBar.hide() return stats def generatePartitionDiffs(self, diffModule, statsInfo={ "partclass": None, "stats": None }, saveFile=False, loadFile=False, tRange=(0, -1), progressBar=None): traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(statsInfo["partclass"]) self.diffObject.setDiffMethod(diffModule) self.numKeys = len( self.partObject.partMethod.getPartitionNum(traces, 0)) numPoints = traces.numPoints() foundsecs = [] if loadFile: cfgsecs = self.api.project().getDataConfig( sectionName="Trace Statistics", subsectionName="Partition Differences") for cfg in cfgsecs: desiredsettings = {} desiredsettings["tracestart"] = tRange[0] desiredsettings["traceend"] = tRange[1] desiredsettings[ "partitiontype"] = self.partObject.partMethod.__class__.__name__ desiredsettings[ "comparetype"] = self.diffObject.mode.moduleName if self.api.project().checkDataConfig(cfg, desiredsettings): foundsecs.append(cfg) else: cfgsecs = [] if len(foundsecs) > 1: IOError("Too many sections!!!") elif len(foundsecs) == 1: fname = self.api.project().convertDataFilepathAbs( foundsecs[0]["filename"]) SADList = np.load(fname) else: progressBar.setWindowTitle( "Phase 2: Calculating Partition Differences") progressBar.setText("Calculating all Differences based on " + self.diffObject.mode.differenceType) SADList = self.diffObject.difference( self.numKeys, self.partObject.partMethod.getNumPartitions(), None, numPoints, statsInfo["stats"], progressBar) if saveFile: cfgsec = self.api.project().addDataConfig( sectionName="Trace Statistics", subsectionName="Partition Differences") cfgsec["tracestart"] = tRange[0] cfgsec["traceend"] = tRange[1] cfgsec[ "partitiontype"] = self.partObject.partMethod.__class__.__name__ cfgsec["comparetype"] = self.diffObject.mode.moduleName fname = self.api.project().getDataFilepath( 'partdiffs-%s-%s-%d-%s.npy' % (cfgsec["partitiontype"], cfgsec["comparetype"], tRange[0], tRange[1]), 'analysis') np.save(fname["abs"], SADList) cfgsec["filename"] = fname["rel"] progressBar.updateStatus(progressBar.maximum) progressBar.setWindowTitle('Debug Fail') if progressBar.wasAborted(): return self.SADList = SADList return SADList def displayPartitions(self, differences={ "partclass": None, "diffs": None }, tRange=(0, -1)): self.graphDock.show() traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(differences["partclass"]) self.numKeys = len( self.partObject.partMethod.getPartitionNum(traces, 0)) self.SADList = differences["diffs"] # Place byte selection option on graph if hasattr(self, 'enabledbytes') and len( self.enabledbytes) == self.numKeys: pass else: self.enabledbytes = [False] * self.numKeys self.doRedraw = True self.byteNumAct = [] for i in range(0, self.numKeys): ql = QToolButton() ql.setText('%d' % i) color = pg.intColor(i, self.numKeys) ql.setStyleSheet("color: rgb(%d, %d, %d)" % (color.red(), color.green(), color.blue())) qa = QWidgetAction(self.graph) qa.setDefaultWidget(ql) qa.setStatusTip('%d' % i) ql.setCheckable(True) ql.setChecked(self.enabledbytes[i]) ql.clicked[bool].connect(partial(self.setBytePlot, i)) self.byteNumAct.append(qa) byteNumAllOn = QAction('All On', self.graph) byteNumAllOff = QAction('All Off', self.graph) byteNumAllOn.triggered.connect(partial(self.setByteAll, True)) byteNumAllOff.triggered.connect(partial(self.setByteAll, False)) self.bselection.clear() for i in range(0, self.numKeys): self.bselection.addAction(self.byteNumAct[i]) self.bselection.addAction(byteNumAllOn) self.bselection.addAction(byteNumAllOff) self.graph.setPersistance(True) self.poi.setDifferences(self.SADList) self.findParam(["Points of Interest", 'poi-pointrng']).setLimits( (0, len(self.SADList[0]))) self.findParam(["Points of Interest", 'poi-pointrng']).setValue( (0, len(self.SADList[0]))) self.redrawPlot() def runAction(self): self.runScriptFunction.emit( 'TraceExplorerDialog_PartitionDisplay_displayPartitionStats') def setTraceSource(self, traces): self._traces = traces self.partObject.setTraceSource(self._traces)
def __init__(self, name=None): GraphWidget.__init__(self) if name is not None: self._name = name ActiveTraceObserver.__init__(self) self.params.addChildren([ { 'name': 'Redraw after Each', 'type': 'bool', 'value': False }, #{'name':'Trace Range', 'key':'tracerng', 'type':'range', 'limits':(0, 0), 'value':(0, 0)}, { 'name': 'Trace(s) to Plot', 'key': 'tracecmd', 'type': 'str', 'value': '0', 'help': '%namehdr%' + "Selects a trace or two to plot. You can specify ranges, individual traces, and colours. Example commands:\n" + " ==================== ========================================================== \n" + " Plot Command Result" " 0 Plots trace #0\n" + " 0-10 Plots trace #0 - #10 inclusive\n" + " 0, 2-5, 9 Plots trace #0, #2-5 inclusive, and #9\n" + " 0(r), 3-6(g), 22(b) Plots trace #0 in red, #3-#6 in green, and #22 in blue\n" + " 2(#F005) Plots trace #2 in red (RGB=F00) with Alpha of 0.3125\n" + " 3(#B0171F) Plots trace #3 in 'india red'\n\n" + " ==================== ========================================================== \n" + "Colour strings are passed to pyqtgraph.mkPen as a string. This means you can specify the following:\n" + " =============== ========================================== \n" + " Colour String Description \n" + " =============== ========================================== \n" + " c One of r, g, b, c, m, y, k, w \n" + " RGB Hexadecimal string, may begin with # \n" + " RGBA Hexadecimal string with alpha value \n" + " RRGGBB \n" + " RRGGBBAA \n" + " =============== ========================================== \n" }, { 'name': 'Point Range', 'key': 'pointrng', 'type': 'rangegraph', 'limits': (0, 0), 'value': (0, 0), 'graphwidget': self }, { 'name': 'Downsampling Mode', 'key': 'dsmode', 'type': 'list', 'values': { 'None': None, 'Subsample': 'subsample', 'Mean': 'mean', 'Peak': 'peak' }, 'value': 'peak', 'action': self.plotInputTrace }, { 'name': 'Y Axis', 'type': 'group', 'expanded': False, 'children': [ { 'name': 'Unity', 'type': 'list', 'values': { "None": "", "Voltage": "V", "Current": "A" }, 'value': "", 'action': self.plotInputTrace }, { 'name': 'Scale Factor', 'type': 'float', 'limits': (1E-9, 1E9), 'value': 1.0, 'action': self.plotInputTrace }, { 'name': 'Offset Factor', 'type': 'float', 'limits': (-1E9, 1E9), 'value': 0.0, 'action': self.plotInputTrace }, ] }, { 'name': 'X Axis', 'type': 'list', 'values': { "Sample": "Pts.", "Time": "s" }, 'value': "Pts.", 'action': self.plotInputTrace }, { 'name': 'T-Statistic', 'key': 'tstat', 'type': 'group', 'expanded': True, 'children': [ { 'name': 'Enable', 'key': 'enable', 'type': 'bool', 'value': False }, { 'name': 'Leakage Type', 'key': 'type', 'type': 'list', 'values': ['Text In', 'Text Out', 'Key', 'None'], 'value': 'Text In' }, { 'name': 'Trace Range', 'key': 'range', 'type': 'range', 'limits': (0, 0), 'value': (0, 0) }, ] }, { 'name': 'Redraw', 'type': 'action', 'action': self.plotInputTrace }, ]) self.findParam('input').setValue( TraceSource.registeredObjects["Trace Management"]) TraceSource.sigRegisteredObjectsChanged.connect( self.traceSourcesChanged) self.resetTraceLimits() self.setDefaultYRange(-0.5, 0.5) self.YDefault()
class PartitionDisplay(Parameterized, AutoScript): _name = "Partition Comparison" def __init__(self, parent): AutoScript.__init__(self) self._autoscript_init = False self.parent = parent self.poi = POI(self) self.poiDock = CWMainGUI.getInstance().addDock(self.poi, "Partition Comparison POI Table", area=Qt.TopDockWidgetArea) self.poiDock.hide() self.defineName() self._traces = None self.api = CWCoreAPI.getInstance() self.graph = GraphWidget() self.bselection = QToolBar() self.graph.addWidget(self.bselection) self.graphDock = CWMainGUI.getInstance().addDock(self.graph, "Partition Comparison Graph", area=Qt.TopDockWidgetArea) self.graphDock.hide() def defineName(self): self.partObject = Partition(self) partModeList = {} for a in self.partObject.supportedMethods: partModeList[a.partitionType] = a self.diffObject = DifferenceMode() diffModeList = {} for a in self.diffObject.supportedMethods: diffModeList[a.differenceType] = a self.addGroup("generatePartitions") self.addGroup("generatePartitionStats") self.addGroup("generatePartitionDiffs") self.addGroup("displayPartitionDiffs") self.getParams().addChildren([ {'name':'Comparison Mode', 'key':'diffmode', 'type':'list', 'values':diffModeList, 'value':self.diffObject.diffMethodClass, 'action':lambda _: self.updateScript()}, {'name':'Partition Mode', 'key':'partmode', 'type':'list', 'values':partModeList, 'value':self.partObject.partMethodClass, 'action':lambda _: self.updateScript()}, {'name':'Display', 'type':'action', 'action':lambda _:self.runAction()}, {'name':'Auto-Save Data to Project', 'key':'part-saveints', 'type':'bool', 'value':False, 'action':lambda _: self.updateScript()}, {'name':'Auto-Load Data from Project', 'key':'part-loadints', 'type':'bool', 'value':False, 'action':lambda _: self.updateScript()}, {'name':'Points of Interest', 'key':'poi', 'type':'group', 'children':[ {'name':'Selection Mode', 'type':'list', 'values':{'Max N Points/Subkey':'maxn'}, 'value':'maxn'}, {'name':'Point Range', 'key':'poi-pointrng', 'type':'range', 'limits':(0, 0), 'default':(0, 0), 'value':(0, 0), 'action':lambda _: self.updatePOI()}, {'name':'Num POI/Subkey', 'key':'poi-nummax', 'type':'int', 'limits':(1, 200), 'value':1, 'action':lambda _: self.updatePOI()}, {'name':'Min Spacing between POI', 'key':'poi-minspace', 'type':'int', 'limits':(1, 100E6), 'value':1, 'step':100, 'action':lambda _: self.updatePOI()}, {'name':'Hill detection', 'key':'poi-hilldet', 'type':'bool', 'value':True, 'tip':"Extend the bounds downhill for each peak", 'action':lambda _: self.updatePOI()}, # {'name':'Threshold', 'key':'threshold', 'type':'int', 'visible':False}, {'name':'Open POI Table', 'type':'action', 'action':lambda _: self.poiDock.show()}, ]}, ]) def updatePOI(self, ignored=None): self.updateScript() if self._autoscript_init == False: return # Some sort of race condition - applying Therac-25 type engineering and just # randomly hope this is enough delay QTimer.singleShot(500, lambda:self.runScriptFunction.emit("TraceExplorerDialog_PartitionDisplay_findPOI")) def setBytePlot(self, num, sel): self.enabledbytes[num] = sel if self.doRedraw: self.redrawPlot() def setByteAll(self, status): self.doRedraw = False for i, t in enumerate(self.byteNumAct): t.defaultWidget().setChecked(status) self.setBytePlot(i, status) self.doRedraw = True self.redrawPlot() def redrawPlot(self): self.graph.clearPushed() for bnum in range(0, self.numKeys): if self.enabledbytes[bnum]: self.graph.setColorInt(bnum, self.numKeys) self.graph.passTrace(self.SADList[bnum], pen=pg.mkPen(pg.intColor(bnum, 16)), idString = str(bnum)) def updateScript(self, ignored=None): ##Partitioning & Differences try: diffMethodStr = self.findParam('diffmode').getValue().__name__ partMethodStr = self.findParam('partmode').getValue().__name__ except AttributeError as e: return self.importsAppend('from chipwhisperer.analyzer.utils.Partition import PartitionRandDebug, PartitionRandvsFixed, PartitionEncKey, PartitionHWIntermediate, PartitionHDLastRound') self.importsAppend('from chipwhisperer.analyzer.utils.TraceExplorerScripts.PartitionDisplay import DifferenceModeTTest, DifferenceModeSAD') self.importsAppend('from chipwhisperer.analyzer.ui.CWAnalyzerGUI import CWAnalyzerGUI') self.addGroup("displayPartitionStats") self.addVariable('displayPartitionStats', 'ted', 'self.') self.addFunction('displayPartitionStats', 'setTraceSource', 'UserScript.traces', obj='ted') self.addFunction('displayPartitionStats', 'parent.getProgressIndicator', '', 'progressBar', obj='ted') self.addFunction('displayPartitionStats', 'partObject.setPartMethod', partMethodStr, obj='ted') self.addFunction('displayPartitionStats', 'partObject.generatePartitions', 'saveFile=True, loadFile=False', 'partData', obj='ted') self.addFunction('displayPartitionStats', 'generatePartitionStats', 'partitionData={"partclass":%s, "partdata":partData}, saveFile=True, progressBar=progressBar' % partMethodStr, 'partStats', obj='ted') self.addFunction('displayPartitionStats', 'generatePartitionDiffs', '%s, statsInfo={"partclass":%s, "stats":partStats}, saveFile=True, loadFile=False, progressBar=progressBar'% (diffMethodStr, partMethodStr), 'partDiffs', obj='ted') self.addFunction('displayPartitionStats', 'displayPartitions', 'differences={"partclass":%s, "diffs":partDiffs}' % partMethodStr, obj='ted') self.addFunction('displayPartitionStats', 'poi.setDifferences', 'partDiffs', obj='ted') ##Points of Interest ptrng = self.findParam(["Points of Interest",'poi-pointrng']).getValue() self.addGroup("findPOI") self.addVariable('findPOI', 'ted', 'self.') self.addFunction('findPOI', 'poi.calcPOI', 'numMax=%d, pointRange=(%d, %d), minSpace=%d' % ( self.findParam(["Points of Interest",'poi-nummax']).getValue(), ptrng[0], ptrng[1], self.findParam(["Points of Interest",'poi-minspace']).getValue()), obj='ted') #Check if this updateScript was called as a result of showing the TraceExplorer window if ignored == "traceexplorer_show": self._autoscript_init = True def generatePartitionStats(self, partitionData={"partclass":None, "partdata":None}, saveFile=False, loadFile=False, tRange=(0, -1), progressBar=None): traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(partitionData["partclass"]) self.numKeys = len(self.partObject.partMethod.getPartitionNum(traces, 0)) numPoints = traces.numPoints() if loadFile: cfgsecs = self.api.project().getDataConfig(sectionName="Trace Statistics", subsectionName="Total Trace Statistics") foundsecs = [] for cfg in cfgsecs: desiredsettings = {} desiredsettings["tracestart"] = tRange[0] desiredsettings["traceend"] = tRange[1] desiredsettings["partitiontype"] = self.partObject.partMethod.__class__.__name__ if self.api.project().checkDataConfig(cfg, desiredsettings): foundsecs.append(cfg) else: foundsecs = [] if len(foundsecs) > 1: IOError("Too many sections!!!") elif len(foundsecs) == 1: fname = self.api.project().convertDataFilepathAbs(foundsecs[0]["filename"]) stats = np.load(fname) else: # Array to hold average + stddev of all traces/partitions A_k = [] A_j = [] Q_k = [] dataArrays = [A_k, A_j, Q_k] ACnt = [] for bnum in range(0, self.numKeys): for d in dataArrays: d.append([]) ACnt.append([]) for i in range(0, self.partObject.partMethod.getNumPartitions()): for d in dataArrays: d[bnum].append(np.zeros(numPoints)) ACnt[bnum].append(0) # Get segment list segList = traces.getSegmentList() if progressBar: progressBar.setWindowTitle("Phase 1: Trace Statistics") progressBar.setMaximum(bnum) # len(segList['offsetList']) * self.numKeys) progressBar.show() # TODO: Double-check this fix # for tsegn, segtrace in enumerate(segList['offsetList']): tsegn = 0 if progressBar: progressBar.setText("Segment %d" % tsegn) # Average data needs to be calculated # Require partition list partData = partitionData["partdata"] # print "Calculating Average + Std-Dev" # Std-Dev calculation: # A[0] = 0 # A[k] = A[k-1] + (x[k] - A[k-1]) / k # Q[0] = 0 # Q[k] = Q[k-1] + (x[k] - A[k-1])(x[k] - A[k]) for bnum in range(0, self.numKeys): progressBar.updateStatus(tsegn * self.numKeys + bnum) if progressBar.wasAborted(): break for i in range(0, self.partObject.partMethod.getNumPartitions()): util.updateUI() tlist = partData[bnum][i] if len(tlist) > 0: for tnum in tlist: if tnum > tRange[0] and tnum < tRange[1]: t = traces.getTrace(tnum) ACnt[bnum][i] += 1 A_k[bnum][i] = A_k[bnum][i] + (t - A_j[bnum][i]) / ACnt[bnum][i] Q_k[bnum][i] = Q_k[bnum][i] + ((t - A_j[bnum][i]) * (t - A_k[bnum][i])) A_j[bnum][i] = A_k[bnum][i] if progressBar.wasAborted(): progressBar.hide() return # Finally get variance for bnum in range(0, self.numKeys): for i in range(0, self.partObject.partMethod.getNumPartitions()): # TODO: Should be using population variance or sample variance (e.g. /n or /n-1)? # Since this is taken over very large sample sizes I imagine it won't matter # ultimately. Q_k[bnum][i] = Q_k[bnum][i] / max(ACnt[bnum][i] - 1, 1) # Average is in A_k stats = {"mean":A_k, "variance":Q_k, "number":ACnt} # Wasn't cancelled - save this to project file for future use if requested if saveFile: progressBar.setText("Saving Mean/Variance Partitions") cfgsec = self.api.project().addDataConfig(sectionName="Trace Statistics", subsectionName="Total Trace Statistics") cfgsec["tracestart"] = tRange[0] cfgsec["traceend"] = tRange[1] cfgsec["partitiontype"] = self.partObject.partMethod.__class__.__name__ fname = self.api.project().getDataFilepath('tracestats-%s-%d-%s.npz' % (cfgsec["partitiontype"], tRange[0], tRange[1]), 'analysis') # Save mean/variance for trace np.savez(fname["abs"], mean=A_k, variance=Q_k, number=ACnt) cfgsec["filename"] = fname["rel"] progressBar.hide() return stats def generatePartitionDiffs(self, diffModule, statsInfo={"partclass":None, "stats":None}, saveFile=False, loadFile=False, tRange=(0, -1), progressBar=None): traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(statsInfo["partclass"]) self.diffObject.setDiffMethod(diffModule) self.numKeys = len(self.partObject.partMethod.getPartitionNum(traces, 0)) numPoints = traces.numPoints() foundsecs = [] if loadFile: cfgsecs = self.api.project().getDataConfig(sectionName="Trace Statistics", subsectionName="Partition Differences") for cfg in cfgsecs: desiredsettings = {} desiredsettings["tracestart"] = tRange[0] desiredsettings["traceend"] = tRange[1] desiredsettings["partitiontype"] = self.partObject.partMethod.__class__.__name__ desiredsettings["comparetype"] = self.diffObject.mode.moduleName if self.api.project().checkDataConfig(cfg, desiredsettings): foundsecs.append(cfg) else: cfgsecs = [] if len(foundsecs) > 1: IOError("Too many sections!!!") elif len(foundsecs) == 1: fname = self.api.project().convertDataFilepathAbs(foundsecs[0]["filename"]) SADList = np.load(fname) else: progressBar.setWindowTitle("Phase 2: Calculating Partition Differences") progressBar.setText("Calculating all Differences based on " + self.diffObject.mode.differenceType) SADList = self.diffObject.difference(self.numKeys, self.partObject.partMethod.getNumPartitions(), None, numPoints, statsInfo["stats"], progressBar) if saveFile: cfgsec = self.api.project().addDataConfig(sectionName="Trace Statistics", subsectionName="Partition Differences") cfgsec["tracestart"] = tRange[0] cfgsec["traceend"] = tRange[1] cfgsec["partitiontype"] = self.partObject.partMethod.__class__.__name__ cfgsec["comparetype"] = self.diffObject.mode.moduleName fname = self.api.project().getDataFilepath('partdiffs-%s-%s-%d-%s.npy' % (cfgsec["partitiontype"], cfgsec["comparetype"], tRange[0], tRange[1]), 'analysis') np.save(fname["abs"], SADList) cfgsec["filename"] = fname["rel"] progressBar.updateStatus(progressBar.maximum) progressBar.setWindowTitle('Debug Fail') if progressBar.wasAborted(): return self.SADList = SADList return SADList def displayPartitions(self, differences={"partclass":None, "diffs":None}, tRange=(0, -1)): self.graphDock.show() traces = self._traces if tRange[1] < 0: tRange = (tRange[0], traces.numTraces() + 1 + tRange[1]) self.partObject.setPartMethod(differences["partclass"]) self.numKeys = len(self.partObject.partMethod.getPartitionNum(traces, 0)) self.SADList = differences["diffs"] # Place byte selection option on graph if hasattr(self, 'enabledbytes') and len(self.enabledbytes) == self.numKeys: pass else: self.enabledbytes = [False] * self.numKeys self.doRedraw = True self.byteNumAct = [] for i in range(0, self.numKeys): ql = QToolButton() ql.setText('%d' % i) color = pg.intColor(i, self.numKeys) ql.setStyleSheet("color: rgb(%d, %d, %d)" % (color.red(), color.green(), color.blue())) qa = QWidgetAction(self.graph) qa.setDefaultWidget(ql) qa.setStatusTip('%d' % i) ql.setCheckable(True) ql.setChecked(self.enabledbytes[i]) ql.clicked[bool].connect(partial(self.setBytePlot, i)) self.byteNumAct.append(qa) byteNumAllOn = QAction('All On', self.graph) byteNumAllOff = QAction('All Off', self.graph) byteNumAllOn.triggered.connect(partial(self.setByteAll, True)) byteNumAllOff.triggered.connect(partial(self.setByteAll, False)) self.bselection.clear() for i in range(0, self.numKeys): self.bselection.addAction(self.byteNumAct[i]) self.bselection.addAction(byteNumAllOn) self.bselection.addAction(byteNumAllOff) self.graph.setPersistance(True) self.poi.setDifferences(self.SADList) self.findParam(["Points of Interest",'poi-pointrng']).setLimits((0, len(self.SADList[0]))) self.findParam(["Points of Interest",'poi-pointrng']).setValue((0, len(self.SADList[0]))) self.redrawPlot() def runAction(self): self.runScriptFunction.emit('TraceExplorerDialog_PartitionDisplay_displayPartitionStats') def setTraceSource(self, traces): self._traces = traces self.partObject.setTraceSource(self._traces)