def PropertyString(self, stype='raw'): if stype == 'attr': result = '' if self.GetValue('Visible') and not self.GetValue('Hidden'): if self.GetValue('KeywordVisible'): if self.GetValue('Keyword') != None and self.GetValue( 'Keyword') != 'None': result = result + self.GetValue('Keyword') + ' ' if self.GetValue('Type') == 'string': value = self.GetValue('Value') elif self.GetValue('Type') == 'file': value = ('/'.join(str( self.GetValue('Value')).split('\\'))).split('/')[-1] elif self.GetValue('Type') == 'int': value = self.GetValue('Value') elif self.GetValue('Type') == 'float': value = str( ToSI(float(self.GetValue('Value')), self.GetValue('Unit'))) else: value = str(self.GetValue('Value')) result = result + value return result elif stype == 'raw': if self.GetValue('Type') == 'string': value = self.GetValue('Value') elif self.GetValue('Type') == 'file': value = self.GetValue('Value') elif self.GetValue('Type') == 'int': value = self.GetValue('Value') elif self.GetValue('Type') == 'float': value = str(float(self.GetValue('Value'))) else: value = str(self.GetValue('Value')) return value elif stype == 'entry': if self.GetValue('Type') == 'string': value = str(self.GetValue('Value')) elif self.GetValue('Type') == 'file': value = str(self.GetValue('Value')) elif self.GetValue('Type') == 'int': value = str(self.GetValue('Value')) elif self.GetValue('Type') == 'float': value = str( ToSI(float(self.GetValue('Value')), self.GetValue('Unit'))) else: value = str(self.GetValue('Value')) return value else: raise ValueError return str(self['Value'])
def __init__(self,pattern,bitRate,amplitude=1.0,risetime=0.,delay=0.,tdOrFs=None): """constructor @param pattern list of bits in pattern which must be 0 or 1 @param bitrate float bitrate in bits/s @param amplitude (optional, defaults to 1.0) float amplitude of zero centered serial data waveform (pk-pk amplitude is twice this value) @param risetime (optional, defaults to 0.0) float risetime of a 1/2 cosine response. @param delay (optional, defaults to 0,0) float delay in time into the pattern. @param tdOrFs (optional, defaults to None) time descriptor or float sample rate. If None is specified, then the descriptor is generated for one pattern length with a sample rate of 10x the bitrate. Otherwise, if a float is specified, then a time descriptor for one pattern length is generated with the sample rate specified. Otherwise the time descriptor specified is used. @return self, a waveform. @throw SignalIntegrityExceptionWaveform exception is raised if the risetime exceeds 59% of the unit interval as this causes the calculation to fail. @todo the failure for a given risetime is due to the simplicity of the algorithm which should be improved at some point. this simplicity is that it only looks at adjacent bits to determine the intersymbol effect of the risetime. @note the left edge of the first bit in the pattern is at the delay time. But because a cosine is used for the risetime emulation, the 50% point of the cosine is reached at this edge. @note the risetime is adjusted if it is too low relative to the sample period. """ if tdOrFs is None: sampleRate=10.*bitRate td=self.TimeDescriptor(bitRate, sampleRate, len(pattern)) elif isinstance(tdOrFs,float): sampleRate=tdOrFs td=self.TimeDescriptor(bitRate, sampleRate, len(pattern)) else: td=tdOrFs T=max(risetime/self.rtvsT,1/td.Fs) patternTimeLength=len(pattern)/bitRate unitInterval=1./bitRate if T>unitInterval: # todo: would like to handle this case in the future raise SignalIntegrityExceptionWaveform('PRBS risetime too high\nfor waveform generation. '+\ 'Limit is '+ToSI(unitInterval*self.rtvsT,'s')+' for given bitrate') v=[0. for _ in range(len(td))] for k in range(len(td)): t=td[k] timeInPattern=((t-delay)%patternTimeLength+patternTimeLength)%patternTimeLength thisBit=int(math.floor(timeInPattern/unitInterval)) timeInBit=timeInPattern-thisBit*unitInterval thisBitValue=pattern[thisBit] if timeInBit>=T/2. and (timeInBit-unitInterval)<=-T/2.: v[k]=2.*amplitude*(thisBitValue-0.5) elif timeInBit<T/2.: previousBit=(thisBit-1+len(pattern))%len(pattern) previousBitTransition=thisBitValue-pattern[previousBit] if previousBitTransition==0: v[k]=2.*amplitude*(thisBitValue-0.5) else: v[k]=amplitude*previousBitTransition*math.cos(math.pi*(timeInBit/T+3./2.)) elif (timeInBit-unitInterval)>-T/2.: nextBit=(thisBit+1)%len(pattern) nextBitTransition=pattern[nextBit]-thisBitValue if nextBitTransition==0: v[k]=2.*amplitude*(thisBitValue-0.5) else: v[k]=amplitude*nextBitTransition*math.cos(math.pi*((timeInBit-unitInterval)/T+3./2.)) Waveform.__init__(self,Waveform(td,v))
def PlotWaveformsTimeDomain(self): self.lift(self.parent.parent) self.plt.cla() self.plt.set_ylabel('amplitude', fontsize=10) self.plotLabel.config(text='Time-domain View') if not SignalIntegrity.App.Preferences['Appearance.PlotCursorValues']: self.plt.format_coord = lambda x, y: '' if not self.waveformList == None: self.plt.autoscale(False) mint = None maxt = None for wfi in range(len(self.waveformList)): wf = self.waveformList[wfi] wfTimes = wf.Times() if len(wfTimes) == 0: continue wfValues = wf.Values() wfName = str(self.waveformNamesList[wfi]) mint = wfTimes[0] if mint is None else min(mint, wfTimes[0]) maxt = wfTimes[-1] if maxt is None else max(maxt, wfTimes[-1]) timeLabel = 's' timeLabelDivisor = 1. if not self.waveformList is None: if (not mint is None) and (not maxt is None): durLabelTime = (maxt - mint) timeLabel = ToSI(durLabelTime, 's')[-2:] timeLabelDivisor = FromSI('1. ' + timeLabel, 's') mint = mint / timeLabelDivisor maxt = maxt / timeLabelDivisor if not mint is None: self.plt.set_xlim(left=mint) if not maxt is None: self.plt.set_xlim(right=maxt) minv = None maxv = None for wfi in range(len(self.waveformList)): wf = self.waveformList[wfi] wfTimes = wf.Times(timeLabelDivisor) if len(wfTimes) == 0: continue wfValues = wf.Values() wfName = str(self.waveformNamesList[wfi]) self.plt.plot(wfTimes, wfValues, label=wfName) minv = min(wfValues) if minv is None else min(minv, min(wfValues)) maxv = max(wfValues) if maxv is None else max(maxv, max(wfValues)) self.plt.set_xlabel('time (' + timeLabel + ')', fontsize=10) self.plt.legend(loc='upper right', labelspacing=0.1) self.plt.set_ylim(bottom=minv) self.plt.set_ylim(top=maxv) self.f.canvas.draw() return self
def Fields2(self,frame,category,parameter,subparameter,label,unit=None): lineFrame=tk.Frame(frame) lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) text=label.ljust(self.labelwidth) line=tk.Label(lineFrame,text=text,font='fixedsys') line.pack(side=tk.LEFT,expand=tk.NO,fill=tk.X) for e in range(len(self.meas[category])): entryFrame=tk.Frame(lineFrame,relief=tk.RIDGE,borderwidth=5) entryFrame.pack(side=tk.LEFT,expand=tk.NO,fill=tk.X) entry=tk.Label(entryFrame,width=self.entrywidth,text=ToSI(self.meas[category][e][parameter][subparameter],unit)) entry.pack(side=tk.LEFT,expand=tk.NO,fill=tk.X)
def UpdateMeasurements(self,meas): self.withdraw() self.meas=meas if self.meas==None: return self.ParametersFrame.pack_forget() self.ParametersFrame=tk.Frame(self.tab1,relief=tk.RIDGE,borderwidth=5) self.ParametersFrame.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES,anchor=tk.NW) self.BERFrame.pack_forget() self.BERFrame=tk.Frame(self.tab2,relief=tk.RIDGE,borderwidth=5) self.BERFrame.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES,anchor=tk.NW) if SignalIntegrity.App.Preferences['Features.OpticalMeasurements']: self.PenaltiesFrame.pack_forget() self.PenaltiesFrame=tk.Frame(self.tab3,relief=tk.RIDGE,borderwidth=5) self.PenaltiesFrame.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES,anchor=tk.NW) self.eyeStatus.set(f"All Measurements Taken at: {10.0**meas['BERForMeasure']}") #topline=''.join(['Eye'.ljust(self.labelwidth)]+[str(eye).center(self.entrywidth-1) for eye in range(len(self.meas['Eye']))]+[''.ljust(self.entrywidth-1)]) self.Heading(self.ParametersFrame,'Eye',[str(e) for e in range(len(self.meas['Eye']))]) #self.Line2(topline) self.Line2(self.ParametersFrame,'Timing') self.Fields2(self.ParametersFrame,'Eye','Start','Time','Start','s') self.Fields2(self.ParametersFrame,'Eye','End','Time','End','s') self.Fields2(self.ParametersFrame,'Eye','Width','Time','Width','s') self.Line2(self.ParametersFrame,'') self.Line2(self.ParametersFrame,'Vertical') self.Fields2(self.ParametersFrame,'Eye','Low','Volt','Low','V') self.Fields2(self.ParametersFrame,'Eye','Mid','Volt','Midpoint','V') self.Fields2(self.ParametersFrame,'Eye','Best','Volt','Best Decision Level','V') self.Fields2(self.ParametersFrame,'Eye','High','Volt','High','V') self.Fields2(self.ParametersFrame,'Eye','Height','Volt','Height','V') self.Fields2(self.ParametersFrame,'Eye','AV','Volt','AV','V') self.Line2(self.ParametersFrame,'') #line=''.join(['Thresholds'.ljust(self.labelwidth)]+[str(th).center(self.entrywidth-1) for th in range(len(self.meas['Level']))]) #self.Line2(line) self.Heading(self.ParametersFrame,'Extents',[str(th) for th in range(len(self.meas['Level']))]) self.Fields2(self.ParametersFrame,'Level','Min','Volt','Min','V') self.Fields2(self.ParametersFrame,'Level', 'Max', 'Volt', 'Max','V') self.Fields2(self.ParametersFrame,'Level', 'Delta', 'Volt', 'Delta','V') self.Fields2(self.ParametersFrame,'Level', 'Mean', 'Volt', 'Mean','V') self.Line2(self.ParametersFrame,'') if len(meas['Eye'])>1: self.SingleLine(self.ParametersFrame,'Eye Linearity',ToSI(self.meas['Linearity']*100.,'%')) try: self.SingleLine(self.ParametersFrame,'RLM',ToSI(self.meas['RLM']*100.,'%')) except: pass self.Line2(self.ParametersFrame,'') self.SingleLine(self.ParametersFrame,'Vertical Resolution',ToSI(self.meas['VerticalResolution'],'V')) self.SingleLine(self.ParametersFrame,'Horizontal Resolution',ToSI(self.meas['HorizontalResolution'],'s')) if 'Probabilities' in self.meas.keys(): # self.measDict['Probabilities']={'SymbolCodes':SymbolCode,'GrayCodes':GrayCodes,'Interpretation':SymbolInterpretedAsOther, # 'ErrorRate':{'Symbol':{'PerSymbol':SymbolErrorRatePerSymbol,'Nominal':NominalSymbolErrorRate,'Measured':MeasuredSymbolErrorRate}, # 'Bit':{'Standard':{'PerSymbol':BitErrorRatePerSymbol,'Nominal':NominalBitErrorRate,'Measured':MeasuredBitErrorRate}, # 'Gray':{'PerSymbol':GrayCodeBitErrorRatePerSymbol,'Nominal':GrayCodeNominalBitErrorRate,'Measured':GrayCodeMeasuredBitErrorRate}}}} SymbolCode=self.meas['Probabilities']['SymbolCodes'] GrayCode=self.meas['Probabilities']['GrayCodes'] numberOfSymbols=len(SymbolCode) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,'Interpretation'.center(self.entrywidth*numberOfSymbols),self.entrywidth*numberOfSymbols) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,'',self.entrywidth) self.AddText(lineFrame,'',self.entrywidth) symbolDigits=math.floor(math.log2(numberOfSymbols)+0.5) for s in SymbolCode: self.AddText(lineFrame,bin(s)[2:].rjust(symbolDigits,'0'),self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,'',self.entrywidth) self.AddText(lineFrame,'',self.entrywidth) symbolDigits=math.floor(math.log2(numberOfSymbols)+0.5) for s in GrayCode: self.AddText(lineFrame,bin(s)[2:].rjust(symbolDigits,'0'),self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,'Symbol',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'Gray Code',self.entrywidth) Probability=self.meas['Probabilities']['Interpretation'] for s in range(len(SymbolCode)): lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,bin(SymbolCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,bin(GrayCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) for o in range(len(SymbolCode)): self.AddEntry(lineFrame, '{:.3E}'.format(Probability[s][o],3), self.entrywidth) # nominal error rates lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,''.center(2*self.entrywidth),2*self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,'Nominal Error Rates'.center(self.entrywidth*numberOfSymbols),self.entrywidth*numberOfSymbols) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,'Symbol',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'Gray Code',self.entrywidth) self.AddText(lineFrame,'Probability',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'SER',self.entrywidth) self.AddText(lineFrame,'BER',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'Gray BER',self.entrywidth) Probability=1./len(SymbolCode) SER=self.meas['Probabilities']['ErrorRate']['Symbol']['PerSymbol'] BER=self.meas['Probabilities']['ErrorRate']['Bit']['Standard']['PerSymbol'] GrayBER=self.meas['Probabilities']['ErrorRate']['Bit']['Gray']['PerSymbol'] for s in range(len(SymbolCode)): lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,bin(SymbolCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,bin(GrayCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(Probability,3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(SER[s],3), self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(BER[s],3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(GrayBER[s],3), self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,'',self.entrywidth) self.AddText(lineFrame,'Totals',self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(1.,3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Symbol']['Nominal'],3), self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Bit']['Standard']['Nominal'],3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Bit']['Gray']['Nominal'],3), self.entrywidth) # measured error rates lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,''.center(2*self.entrywidth),2*self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,''.center(self.entrywidth),self.entrywidth) self.AddText(lineFrame,'Measured Error Rates'.center(self.entrywidth*numberOfSymbols),self.entrywidth*numberOfSymbols) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,'Symbol',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'Gray Code',self.entrywidth) self.AddText(lineFrame,'Probability',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'SER',self.entrywidth) self.AddText(lineFrame,'BER',self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,'Gray BER',self.entrywidth) Probability=self.meas['Probabilities']['Symbol'] SER=self.meas['Probabilities']['ErrorRate']['Symbol']['PerSymbol'] BER=self.meas['Probabilities']['ErrorRate']['Bit']['Standard']['PerSymbol'] GrayBER=self.meas['Probabilities']['ErrorRate']['Bit']['Gray']['PerSymbol'] for s in range(len(SymbolCode)): lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,bin(SymbolCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) if numberOfSymbols > 2: self.AddText(lineFrame,bin(GrayCode[s])[2:].rjust(symbolDigits,'0'),self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(Probability[s],3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(SER[s],3), self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(BER[s],3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(GrayBER[s],3), self.entrywidth) lineFrame=tk.Frame(self.BERFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) if numberOfSymbols > 2: self.AddText(lineFrame,'',self.entrywidth) self.AddText(lineFrame,'Totals',self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(sum(Probability),3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Symbol']['Measured'],3), self.entrywidth) self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Bit']['Standard']['Measured'],3), self.entrywidth) if numberOfSymbols > 2: self.AddEntry(lineFrame, '{:.3E}'.format(self.meas['Probabilities']['ErrorRate']['Bit']['Gray']['Measured'],3), self.entrywidth) self.tabControl.tab(1,state='normal') else: self.tabControl.tab(1,state='disabled') # self.measDict['Penalties']={'PH':PH,'PL':PL,'MA':OMA,'QFactorExpected':QFactorExpected,'QFactorExpecteddB':QFactorExpecteddB, # 'BERMeasured':BERmeas,'BERExpected':BERexpected, # 'QFactor':QFactor,'QFactordB':QFactordB,'TxPenalty':TxPenalty, # 'NoiseSigma':self.NoiseSigma, # 'Levels':{'Total':numLevels,'Inner':numInnerLevels,'Outer':numOuterLevels}, # 'Eyes':numEyes,'ErrorCases':numErrorCases, # 'F':{'Numerical':F,'Numerator':FN,'Denominator':FD}, # 'D':D} if SignalIntegrity.App.Preferences['Features.OpticalMeasurements']: if 'Penalties' in self.meas.keys(): PH=self.meas['Penalties']['PH'] self.SingleLine(self.PenaltiesFrame, 'High Level', ToSI(PH,round=6)) PL=self.meas['Penalties']['PL'] self.SingleLine(self.PenaltiesFrame, 'Low Level', ToSI(PL,round=6)) OMA=self.meas['Penalties']['MA'] self.SingleLine(self.PenaltiesFrame, 'Modulation Amplitude', ToSI(OMA,round=6)) sigma=self.meas['Penalties']['NoiseSigma'] self.SingleLine(self.PenaltiesFrame, 'Noise Sigma', ToSI(sigma,round=6)) noisePenaltydB=self.meas['Penalties']['NoisePenalty'] self.SingleLine(self.PenaltiesFrame, 'Noise Penalty', ToSI(noisePenaltydB,'dB',round=4)) QFactorExpected=self.meas['Penalties']['QFactorExpected'] self.SingleLine(self.PenaltiesFrame, 'Expected Q Factor', ToSI(QFactorExpected,round=6)) BERexpected=self.meas['Penalties']['BERExpected'] self.SingleLine(self.PenaltiesFrame, 'Expected BER', '{:.3E}'.format(BERexpected)) lineFrame=tk.Frame(self.PenaltiesFrame); lineFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO) self.AddText(lineFrame,'',self.entrywidth) BERmeas=self.meas['Penalties']['BERMeasured'] self.SingleLine(self.PenaltiesFrame, 'Measured BER', '{:.3E}'.format(BERmeas)) QFactor=self.meas['Penalties']['QFactor'] self.SingleLine(self.PenaltiesFrame, 'Measured Q Factor', 'infinite' if math.isinf(QFactor) else ToSI(QFactor,round=6)) TxPenalty=self.meas['Penalties']['TxPenalty'] if BERexpected == 0 and BERmeas == 0: self.SingleLine(self.PenaltiesFrame, 'Tx Penalty (dB power)', 'unknown') else: self.SingleLine(self.PenaltiesFrame, 'Tx Penalty (dB power)', 'infinite' if math.isinf(TxPenalty) else ToSI(TxPenalty,'dB',round=4)) self.tabControl.tab(2,state='normal') else: self.tabControl.tab(2,state='disabled') self.deiconify()
def PlotSParameter(self): import SignalIntegrity.Lib as si self.topLeftPlot.cla() self.topRightPlot.cla() self.bottomLeftPlot.cla() self.bottomRightPlot.cla() if not SignalIntegrity.App.Preferences['Appearance.PlotCursorValues']: self.topLeftPlot.format_coord = lambda x, y: '' self.topRightPlot.format_coord = lambda x, y: '' self.bottomLeftPlot.format_coord = lambda x, y: '' self.bottomRightPlot.format_coord = lambda x, y: '' fr=self.sp.FrequencyResponse(self.toPort,self.fromPort) ir=fr.ImpulseResponse() y=fr.Response('dB') self.freqLabel=ToSI(fr.Frequencies()[-1],'Hz')[-3:] freqLabelDivisor=FromSI('1. '+self.freqLabel,'Hz') x=fr.Frequencies(freqLabelDivisor) if self.showPassivityViolations.get(): self.passivityViolations=[] s=self.sp._LargestSingularValues() for n in range(len(s)): if s[n]-1 > 1e-15: dotsize=max(min(20.,math.log10(s[0])/math.log10(1.01)*20.),1e-15) self.passivityViolations.append([x[n],y[n],dotsize]) lw=[min(1.,math.sqrt(w))*1.5 for w in fr.Response('mag')] fastway=True # this works - properly displays on log plot, only it is just too slow! # if self.logScale.get(): # fastway=False if self.variableLineWidth.get(): if fastway: segments = [[[x[i],y[i]],[x[i+1],y[i+1]]] for i in range(len(x)-1)] slw=lw[:-1] lc = LineCollection(segments, linewidths=slw,color='blue') self.topLeftPlot.add_collection(lc) else: for i in range(len(x)-1): if self.logScale.get(): self.topLeftPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue') else: self.topLeftPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue') else: if self.logScale.get(): self.topLeftPlot.semilogx(x,y) else: self.topLeftPlot.plot(x,y) if self.showPassivityViolations.get(): self.topLeftPlot.scatter( [c[0] for c in self.passivityViolations], [c[1] for c in self.passivityViolations], s=[c[2] for c in self.passivityViolations], color='red') self.topLeftPlot.set_xlim(xmin=min(x)) self.topLeftPlot.set_xlim(xmax=max(x)) self.topLeftPlot.set_ylim(ymin=max(min(y)-1.,-60.0)) self.topLeftPlot.set_ylim(ymax=max(y)+1.) self.topLeftPlot.set_ylabel('magnitude (dB)',fontsize=10) self.topLeftPlot.set_xlabel('frequency ('+self.freqLabel+')',fontsize=10) y=fr.Response('deg') x=fr.Frequencies(freqLabelDivisor) if self.variableLineWidth.get(): if fastway: segments = [[[x[i],y[i]],[x[i+1],y[i+1]]] for i in range(len(x)-1)] slw=lw[:-1] lc = LineCollection(segments, linewidths=slw,color='blue') self.topRightPlot.add_collection(lc) else: for i in range(len(x)-1): if self.logScale.get(): self.topRightPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue') else: self.topRightPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue') else: if self.logScale.get(): self.topRightPlot.semilogx(x,y) else: self.topRightPlot.plot(x,y) self.topRightPlot.set_xlim(xmin=min(x)) self.topRightPlot.set_xlim(xmax=max(x)) self.topRightPlot.set_ylim(ymin=min(y)-1) self.topRightPlot.set_ylim(ymax=max(y)+1) self.topRightPlot.set_ylabel('phase (degrees)',fontsize=10) self.topRightPlot.set_xlabel('frequency ('+self.freqLabel+')',fontsize=10) if ir is not None: if self.buttonLabels[self.toPort-1][self.fromPort-1][:2]=='i/' or self.buttonLabels[self.toPort-1][self.fromPort-1][:3]=='di/': print('Integrate') ir=si.td.wf.ImpulseResponse(ir.Integral(addPoint=False)) if self.buttonLabels[self.toPort-1][self.fromPort-1][:3]=='di/': print('Integrate') ir=si.td.wf.ImpulseResponse(ir.Integral(addPoint=False)*ir.td.Fs) y=ir.Values() timeLabel=ToSI(ir.Times()[-1],'s')[-2:] timeLabelDivisor=FromSI('1. '+timeLabel,'s') x=ir.Times(timeLabelDivisor) self.bottomLeftPlot.plot(x,y) if self.showCausalityViolations.get(): self.causalityViolations=[] Ts=1./ir.td.Fs/1e-9 for k in range(len(x)): if x[k]<=-Ts and abs(y[k])>0: dotsize=max(min(20.,abs(y[k])/0.1*20.),1e-15) self.causalityViolations.append([x[k],y[k],dotsize]) self.bottomLeftPlot.scatter( [c[0] for c in self.causalityViolations], [c[1] for c in self.causalityViolations], s=[c[2] for c in self.causalityViolations], color='red') self.bottomLeftPlot.set_ylim(ymin=min(min(y)*1.05,-0.1)) self.bottomLeftPlot.set_ylim(ymax=max(max(y)*1.05,0.1)) self.bottomLeftPlot.set_xlim(xmin=min(x)) self.bottomLeftPlot.set_xlim(xmax=max(x)) self.bottomLeftPlot.set_ylabel('amplitude',fontsize=10) self.bottomLeftPlot.set_xlabel('time ('+timeLabel+')',fontsize=10) firFilter=ir.FirFilter() stepWaveformTimeDescriptor=ir.td/firFilter.FilterDescriptor() stepWaveform=si.td.wf.StepWaveform(stepWaveformTimeDescriptor) stepResponse=stepWaveform*firFilter y=stepResponse.Values() x=stepResponse.Times(timeLabelDivisor) if self.showImpedance.get() and (self.fromPort == self.toPort): Z0=self.referenceImpedance.GetValue() y=[3000. if (1-yv)<=.000001 else min(Z0*(1+yv)/(1-yv),3000) for yv in y] x=[xv/2 for xv in x] self.bottomRightPlot.set_ylabel('impedance (Ohms)',fontsize=10) self.bottomRightPlot.set_xlabel('length ('+timeLabel+')',fontsize=10) self.bottomRightPlot.set_ylim(ymin=min(min(y)*1.05,Z0-1)) else: self.bottomRightPlot.set_ylabel('amplitude',fontsize=10) self.bottomRightPlot.set_xlabel('time ('+timeLabel+')',fontsize=10) self.bottomRightPlot.set_ylim(ymin=min(min(y)*1.05,-0.1)) self.bottomRightPlot.plot(x,y) self.bottomRightPlot.set_ylim(ymax=max(max(y)*1.05,0.1)) self.bottomRightPlot.set_xlim(xmin=min(x)) self.bottomRightPlot.set_xlim(xmax=max(x)) self.topLeftCanvas.draw() self.topRightCanvas.draw() self.bottomLeftCanvas.draw() self.bottomRightCanvas.draw()
def PlotWaveformsFrequencyContent(self, density=False): self.lift(self.parent.parent) self.plt.cla() import SignalIntegrity.Lib as si fd = si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']) if not SignalIntegrity.App.Preferences['Appearance.PlotCursorValues']: self.plt.format_coord = lambda x, y: '' if not self.waveformList == None: self.plt.autoscale(False) self.frequencyContentList = [ wf.FrequencyContent().LimitEndFrequency( SignalIntegrity.App. Project['CalculationProperties.EndFrequency']) for wf in self.waveformList ] minf = None maxf = None for wfi in range(len(self.waveformList)): fc = self.frequencyContentList[wfi] fcFrequencies = fc.Frequencies() if len(fcFrequencies) == 0: continue fcValues = fc.Values('dBm') fcName = str(self.waveformNamesList[wfi]) minf = fcFrequencies[0] if minf is None else min( minf, fcFrequencies[0]) maxf = fcFrequencies[-1] if maxf is None else max( maxf, fcFrequencies[-1]) freqLabel = 'Hz' freqLabelDivisor = 1. if not self.waveformList is None: if (not minf is None) and (not maxf is None): durLabelFrequency = (maxf - minf) freqLabel = ToSI(durLabelFrequency, 'Hz')[-3:] freqLabelDivisor = FromSI('1. ' + freqLabel, 'Hz') minf = minf / freqLabelDivisor maxf = maxf / freqLabelDivisor if not minf is None: self.plt.set_xlim(left=minf) if not maxf is None: self.plt.set_xlim(right=maxf) if density: self.plotLabel.config(text='Spectral Density') self.plt.set_ylabel('magnitude (dBm/' + freqLabel + ')', fontsize=10) else: self.plotLabel.config(text='Spectral Content') self.plt.set_ylabel('magnitude (dBm)', fontsize=10) minv = None maxv = None minvStd = None for wfi in range(len(self.frequencyContentList)): fc = self.frequencyContentList[wfi] fcFrequencies = fc.Frequencies(freqLabelDivisor) if len(fcFrequencies) == 0: continue if density: adder = 10. * math.log10(freqLabelDivisor) fcValues = [v + adder for v in fc.Values('dBmPerHz')] else: fcValues = fc.Values('dBm') minv = min(fcValues) if minv is None else min(minv, min(fcValues)) maxv = max(fcValues) if maxv is None else max(maxv, max(fcValues)) minvStd = mean( fcValues) - 0.5 * std(fcValues) if minvStd is None else min( minvStd, mean(fcValues) - 0.5 * std(fcValues)) fcName = str(self.waveformNamesList[wfi]) self.plt.plot(fcFrequencies, fcValues, label=fcName) minv = max(minv, minvStd) self.plt.set_xlabel('frequency (' + freqLabel + ')', fontsize=10) self.plt.legend(loc='upper right', labelspacing=0.1) self.plt.set_ylim(bottom=minv) self.plt.set_ylim(top=maxv) self.f.canvas.draw() return self