class SignalIntegrityAppHeadless(object): def __init__(self): # make absolutely sure the directory of this file is the first in the # python path thisFileDir = os.path.dirname(os.path.realpath(__file__)) sys.path = [thisFileDir] + sys.path SignalIntegrity.App.Preferences = Preferences() SignalIntegrity.App.InstallDir = os.path.dirname( os.path.abspath(__file__)) self.Drawing = DrawingHeadless(self) def NullCommand(self): pass def OpenProjectFile(self, filename): if filename is None: filename = '' if isinstance(filename, tuple): filename = '' filename = str(filename) if filename == '': return False try: self.fileparts = FileParts(filename) os.chdir(self.fileparts.AbsoluteFilePath()) self.fileparts = FileParts(filename) SignalIntegrity.App.Project = ProjectFile().Read( self.fileparts.FullFilePathExtension('.si')) self.Drawing.InitFromProject() except: return False self.Drawing.schematic.Consolidate() for device in self.Drawing.schematic.deviceList: device.selected = False for wireProject in SignalIntegrity.App.Project[ 'Drawing.Schematic.Wires']: for vertexProject in wireProject['Vertices']: vertexProject['Selected'] = False return True def SaveProjectToFile(self, filename): self.fileparts = FileParts(filename) os.chdir(self.fileparts.AbsoluteFilePath()) self.fileparts = FileParts(filename) SignalIntegrity.App.Project.Write(self, filename) def SaveProject(self): if self.fileparts.filename == '': return filename = self.fileparts.AbsoluteFilePath( ) + '/' + self.fileparts.FileNameWithExtension(ext='.si') self.SaveProjectToFile(filename) def config(self, cursor=None): pass def CalculateSParameters(self): netList = self.Drawing.schematic.NetList().Text() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] spnp = si.p.SystemSParametersNumericParser( si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App. Project['CalculationProperties.EndFrequency'], SignalIntegrity. App.Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) spnp.AddLines(netList) try: sp = spnp.SParameters() except si.SignalIntegrityException as e: return None return (sp, self.fileparts.FullFilePathExtension('s' + str(sp.m_P) + 'p')) def Simulate(self): netList = self.Drawing.schematic.NetList() netListText = netList.Text() import SignalIntegrity.Lib as si fd = si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']) cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] snp = si.p.SimulatorNumericParser(fd, cacheFileName=cacheFileName) snp.AddLines(netListText) try: transferMatrices = snp.TransferMatrices() except si.SignalIntegrityException as e: return None outputWaveformLabels = netList.OutputNames() try: inputWaveformList = self.Drawing.schematic.InputWaveforms() sourceNames = netList.SourceNames() except si.SignalIntegrityException as e: return None transferMatricesProcessor = si.td.f.TransferMatricesProcessor( transferMatrices) si.td.wf.Waveform.adaptionStrategy = 'SinX' if SignalIntegrity.App.Preferences[ 'Calculation.UseSinX'] else 'Linear' try: outputWaveformList = transferMatricesProcessor.ProcessWaveforms( inputWaveformList) except si.SignalIntegrityException as e: return None for outputWaveformIndex in range(len(outputWaveformList)): outputWaveform = outputWaveformList[outputWaveformIndex] outputWaveformLabel = outputWaveformLabels[outputWaveformIndex] for device in self.Drawing.schematic.deviceList: if device['partname'].GetValue() in [ 'Output', 'DifferentialVoltageOutput', 'CurrentOutput' ]: if device['ref'].GetValue() == outputWaveformLabel: # probes may have different kinds of gain specified gainProperty = device['gain'] gain = gainProperty.GetValue() offset = device['offset'].GetValue() delay = device['td'].GetValue() if gain != 1.0 or offset != 0.0 or delay != 0.0: outputWaveform = outputWaveform.DelayBy( delay) * gain + offset outputWaveformList[ outputWaveformIndex] = outputWaveform break userSampleRate = SignalIntegrity.App.Project[ 'CalculationProperties.UserSampleRate'] outputWaveformList = [ wf.Adapt( si.td.wf.TimeDescriptor( wf.td.H, int(wf.td.K * userSampleRate / wf.td.Fs), userSampleRate)) for wf in outputWaveformList ] return (sourceNames, outputWaveformLabels, transferMatrices, outputWaveformList) def VirtualProbe(self): netList = self.Drawing.schematic.NetList() netListText = netList.Text() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] snp = si.p.VirtualProbeNumericParser(si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) snp.AddLines(netListText) try: transferMatrices = snp.TransferMatrices() except si.SignalIntegrityException as e: return None transferMatricesProcessor = si.td.f.TransferMatricesProcessor( transferMatrices) si.td.wf.Waveform.adaptionStrategy = 'SinX' if SignalIntegrity.App.Preferences[ 'Calculation.UseSinX'] else 'Linear' try: inputWaveformList = self.Drawing.schematic.InputWaveforms() sourceNames = netList.MeasureNames() except si.SignalIntegrityException as e: return None try: outputWaveformList = transferMatricesProcessor.ProcessWaveforms( inputWaveformList) except si.SignalIntegrityException as e: return None outputWaveformLabels = netList.OutputNames() for outputWaveformIndex in range(len(outputWaveformList)): outputWaveform = outputWaveformList[outputWaveformIndex] outputWaveformLabel = outputWaveformLabels[outputWaveformIndex] for device in self.Drawing.schematic.deviceList: if device['partname'].GetValue() in [ 'Output', 'DifferentialVoltageOutput', 'CurrentOutput' ]: if device['ref'].GetValue() == outputWaveformLabel: # probes may have different kinds of gain specified gainProperty = device['gain'] gain = gainProperty.GetValue() offset = device['offset'].GetValue() delay = device['td'].GetValue() if gain != 1.0 or offset != 0.0 or delay != 0.0: outputWaveform = outputWaveform.DelayBy( delay) * gain + offset outputWaveformList[ outputWaveformIndex] = outputWaveform break userSampleRate = SignalIntegrity.App.Project[ 'CalculationProperties.UserSampleRate'] outputWaveformList = [ wf.Adapt( si.td.wf.TimeDescriptor( wf.td.H, int(wf.td.K * userSampleRate / wf.td.Fs), userSampleRate)) for wf in outputWaveformList ] return (sourceNames, outputWaveformLabels, transferMatrices, outputWaveformList) def Deembed(self): netList = self.Drawing.schematic.NetList().Text() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] dnp = si.p.DeembedderNumericParser(si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) dnp.AddLines(netList) try: sp = dnp.Deembed() except si.SignalIntegrityException as e: return None unknownNames = dnp.m_sd.UnknownNames() if len(unknownNames) == 1: sp = [sp] return (unknownNames, sp) filename = [] for u in range(len(unknownNames)): extension = '.s' + str(sp[u].m_P) + 'p' filename = unknownNames[u] + extension if self.fileparts.filename != '': filename.append(self.fileparts.filename + '_' + filename) return (unknownNames, sp, filename)
class SignalIntegrityAppHeadless(object): projectStack = ProjectStack() def __init__(self): # make absolutely sure the directory of this file is the first in the # python path thisFileDir = os.path.dirname(os.path.realpath(__file__)) sys.path = [thisFileDir] + sys.path SignalIntegrity.App.Preferences = Preferences() SignalIntegrity.App.InstallDir = os.path.dirname( os.path.abspath(__file__)) self.Drawing = DrawingHeadless(self) def NullCommand(self): pass def OpenProjectFile(self, filename): if filename is None: filename = '' if isinstance(filename, tuple): filename = '' filename = str(filename) if filename == '': return False try: self.fileparts = FileParts(filename) os.chdir(self.fileparts.AbsoluteFilePath()) self.fileparts = FileParts(filename) SignalIntegrity.App.Project = ProjectFile().Read( self.fileparts.FullFilePathExtension('.si')) self.Drawing.InitFromProject() except: return False self.Drawing.schematic.Consolidate() for device in self.Drawing.schematic.deviceList: device.selected = False for wireProject in SignalIntegrity.App.Project[ 'Drawing.Schematic.Wires']: for vertexProject in wireProject['Vertices']: vertexProject['Selected'] = False return True def SaveProjectToFile(self, filename): self.fileparts = FileParts(filename) os.chdir(self.fileparts.AbsoluteFilePath()) self.fileparts = FileParts(filename) SignalIntegrity.App.Project.Write(self, filename) def SaveProject(self): if self.fileparts.filename == '': return filename = self.fileparts.AbsoluteFilePath( ) + '/' + self.fileparts.FileNameWithExtension(ext='.si') self.SaveProjectToFile(filename) def NetListText(self): return self.Drawing.schematic.NetList().Text( ) + SignalIntegrity.App.Project['PostProcessing'].NetListLines() def config(self, cursor=None): pass def CalculateSParameters(self): import SignalIntegrity.Lib as si if not hasattr(self.Drawing, 'canCalculate'): self.Drawing.DrawSchematic() if self.Drawing.canCalculateSParametersFromNetworkAnalyzerModel: try: sp = self.SimulateNetworkAnalyzerModel(SParameters=True) except si.SignalIntegrityException as e: return None return (sp, self.fileparts.FullFilePathExtension('s' + str(sp.m_P) + 'p')) elif not self.Drawing.canCalculateSParameters: return None netListText = self.NetListText() cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] spnp = si.p.SystemSParametersNumericParser( si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App. Project['CalculationProperties.EndFrequency'], SignalIntegrity. App.Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) spnp.AddLines(netListText) try: sp = spnp.SParameters() except si.SignalIntegrityException as e: return None return (sp, self.fileparts.FullFilePathExtension('s' + str(sp.m_P) + 'p')) def Simulate(self): if not hasattr(self.Drawing, 'canCalculate'): self.Drawing.DrawSchematic() if self.Drawing.canSimulateNetworkAnalyzerModel: return self.SimulateNetworkAnalyzerModel(SParameters=False) elif not self.Drawing.canSimulate: return None netList = self.Drawing.schematic.NetList() netListText = self.NetListText() import SignalIntegrity.Lib as si fd = si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']) cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] snp = si.p.SimulatorNumericParser(fd, cacheFileName=cacheFileName) snp.AddLines(netListText) try: transferMatrices = snp.TransferMatrices() except si.SignalIntegrityException as e: return None outputWaveformLabels = netList.OutputNames() try: inputWaveformList = self.Drawing.schematic.InputWaveforms() sourceNames = netList.SourceNames() except si.SignalIntegrityException as e: return None transferMatricesProcessor = si.td.f.TransferMatricesProcessor( transferMatrices) si.td.wf.Waveform.adaptionStrategy = 'SinX' if SignalIntegrity.App.Preferences[ 'Calculation.UseSinX'] else 'Linear' try: outputWaveformList = transferMatricesProcessor.ProcessWaveforms( inputWaveformList) except si.SignalIntegrityException as e: return None for outputWaveformIndex in range(len(outputWaveformList)): outputWaveform = outputWaveformList[outputWaveformIndex] outputWaveformLabel = outputWaveformLabels[outputWaveformIndex] for device in self.Drawing.schematic.deviceList: if device['partname'].GetValue() in [ 'Output', 'DifferentialVoltageOutput', 'CurrentOutput' ]: if device['ref'].GetValue() == outputWaveformLabel: # probes may have different kinds of gain specified gainProperty = device['gain'] gain = gainProperty.GetValue() offset = device['offset'].GetValue() delay = device['td'].GetValue() if gain != 1.0 or offset != 0.0 or delay != 0.0: outputWaveform = outputWaveform.DelayBy( delay) * gain + offset outputWaveformList[ outputWaveformIndex] = outputWaveform break userSampleRate = SignalIntegrity.App.Project[ 'CalculationProperties.UserSampleRate'] outputWaveformList = [ wf.Adapt( si.td.wf.TimeDescriptor( wf.td.H, int(wf.td.K * userSampleRate / wf.td.Fs), userSampleRate)) for wf in outputWaveformList ] return (sourceNames, outputWaveformLabels, transferMatrices, outputWaveformList) def VirtualProbe(self): netList = self.Drawing.schematic.NetList() netListText = self.NetListText() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] snp = si.p.VirtualProbeNumericParser(si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) snp.AddLines(netListText) try: transferMatrices = snp.TransferMatrices() except si.SignalIntegrityException as e: return None transferMatricesProcessor = si.td.f.TransferMatricesProcessor( transferMatrices) si.td.wf.Waveform.adaptionStrategy = 'SinX' if SignalIntegrity.App.Preferences[ 'Calculation.UseSinX'] else 'Linear' try: inputWaveformList = self.Drawing.schematic.InputWaveforms() sourceNames = netList.MeasureNames() except si.SignalIntegrityException as e: return None try: outputWaveformList = transferMatricesProcessor.ProcessWaveforms( inputWaveformList) except si.SignalIntegrityException as e: return None outputWaveformLabels = netList.OutputNames() for outputWaveformIndex in range(len(outputWaveformList)): outputWaveform = outputWaveformList[outputWaveformIndex] outputWaveformLabel = outputWaveformLabels[outputWaveformIndex] for device in self.Drawing.schematic.deviceList: if device['partname'].GetValue() in [ 'Output', 'DifferentialVoltageOutput', 'CurrentOutput' ]: if device['ref'].GetValue() == outputWaveformLabel: # probes may have different kinds of gain specified gainProperty = device['gain'] gain = gainProperty.GetValue() offset = device['offset'].GetValue() delay = device['td'].GetValue() if gain != 1.0 or offset != 0.0 or delay != 0.0: outputWaveform = outputWaveform.DelayBy( delay) * gain + offset outputWaveformList[ outputWaveformIndex] = outputWaveform break userSampleRate = SignalIntegrity.App.Project[ 'CalculationProperties.UserSampleRate'] outputWaveformList = [ wf.Adapt( si.td.wf.TimeDescriptor( wf.td.H, int(wf.td.K * userSampleRate / wf.td.Fs), userSampleRate)) for wf in outputWaveformList ] return (sourceNames, outputWaveformLabels, transferMatrices, outputWaveformList) def Deembed(self): netListText = self.NetListText() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] dnp = si.p.DeembedderNumericParser(si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) dnp.AddLines(netListText) try: sp = dnp.Deembed() except si.SignalIntegrityException as e: return None unknownNames = dnp.m_sd.UnknownNames() if len(unknownNames) == 1: sp = [sp] return (unknownNames, sp) filename = [] for u in range(len(unknownNames)): extension = '.s' + str(sp[u].m_P) + 'p' filename = unknownNames[u] + extension if self.fileparts.filename != '': filename.append(self.fileparts.filename + '_' + filename) return (unknownNames, sp, filename) def CalculateErrorTerms(self): if not hasattr(self.Drawing, 'canCalculate'): self.Drawing.DrawSchematic() if not self.Drawing.canCalculateErrorTerms: return None netList = self.Drawing.schematic.NetList() netListText = self.NetListText() import SignalIntegrity.Lib as si cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] etnp = si.p.CalibrationNumericParser(si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']), cacheFileName=cacheFileName) etnp.AddLines(netListText) try: cal = etnp.CalculateCalibration() except si.SignalIntegrityException as e: return None return (cal, self.fileparts.FullFilePathExtension('cal')) def Device(self, ref): """ accesses a device by it's reference string @param ref string reference designator @return device if found otherwise None Some examples of how to use this (proj is a project name) gain=proj.Device('U1')['gain']['Value'] proj.Device('U1')['gain']['Value']=gain """ devices = self.Drawing.schematic.deviceList for device in devices: if device['ref']['Value'] == ref: return device return None def SimulateNetworkAnalyzerModel(self, SParameters=False): netList = self.Drawing.schematic.NetList().Text() import SignalIntegrity.Lib as si fd = si.fd.EvenlySpacedFrequencyList( SignalIntegrity.App.Project['CalculationProperties.EndFrequency'], SignalIntegrity.App. Project['CalculationProperties.FrequencyPoints']) cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle() + '_DUTSParameters' si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] spnp = si.p.DUTSParametersNumericParser(fd, cacheFileName=cacheFileName) spnp.AddLines(netList) try: (DUTSp, NetworkAnalyzerProjectFile) = spnp.SParameters() except si.SignalIntegrityException as e: return None netListText = None if NetworkAnalyzerProjectFile != None: level = SignalIntegrityAppHeadless.projectStack.Push() try: app = SignalIntegrityAppHeadless() if app.OpenProjectFile( os.path.realpath(NetworkAnalyzerProjectFile)): app.Drawing.DrawSchematic() netList = app.Drawing.schematic.NetList() netListText = netList.Text() else: pass except: pass finally: SignalIntegrityAppHeadless.projectStack.Pull(level) else: netList = self.Drawing.schematic.NetList() netListText = self.NetListText() if netListText == None: return None cacheFileName = None if SignalIntegrity.App.Preferences['Cache.CacheResults']: cacheFileName = self.fileparts.FileNameTitle( ) + '_TransferMatrices' si.sd.Numeric.trySVD = SignalIntegrity.App.Preferences[ 'Calculation.TrySVD'] snp = si.p.NetworkAnalyzerSimulationNumericParser( fd, DUTSp, spnp.NetworkAnalyzerPortConnectionList, cacheFileName=cacheFileName) snp.AddLines(netListText) level = SignalIntegrityAppHeadless.projectStack.Push() try: os.chdir( FileParts(os.path.abspath( NetworkAnalyzerProjectFile)).AbsoluteFilePath()) transferMatrices = snp.TransferMatrices() except si.SignalIntegrityException as e: return None finally: SignalIntegrityAppHeadless.projectStack.Pull(level) sourceNames = snp.m_sd.SourceVector() gdoDict = {} if NetworkAnalyzerProjectFile != None: level = SignalIntegrityAppHeadless.projectStack.Push() try: app = SignalIntegrityAppHeadless() if app.OpenProjectFile( os.path.realpath(NetworkAnalyzerProjectFile)): app.Drawing.DrawSchematic() # get output gain, offset, delay for name in [rdn[2] for rdn in snp.m_sd.pOutputList]: gdoDict[name] = { 'gain': float(app.Device(name)['gain']['Value']), 'offset': float(app.Device(name)['offset']['Value']), 'delay': float(app.Device(name)['td']['Value']) } stateList = [ app.Device(sourceNames[port])['state']['Value'] for port in range(snp.simulationNumPorts) ] self.wflist = [] for driven in range(snp.simulationNumPorts): thiswflist = [] for port in range(snp.simulationNumPorts): app.Device(sourceNames[port])['state'][ 'Value'] = 'on' if port == driven else 'off' for wfIndex in range(len(sourceNames)): thiswflist.append( app.Device(sourceNames[wfIndex]).Waveform()) self.wflist.append(thiswflist) for port in range(snp.simulationNumPorts): app.Device(sourceNames[port] )['state']['Value'] = stateList[port] else: pass except: pass finally: SignalIntegrityAppHeadless.projectStack.Pull(level) else: stateList = [ app.Device(sourceNames[port])['state']['Value'] for port in range(snp.simulationNumPorts) ] self.wflist = [] for name in [rdn[2] for rdn in snp.m_sd.pOutputList]: gdoDict[name] = { 'gain': float(app.Device()[name]['gain']['Value']), 'offset': float(app.Device()[name]['offset']['Value']), 'delay': float(app.Device()[name]['td']['Value']) } for driven in range(snp.simulationNumPorts): thiswflist = [] for port in range(snp.simulationNumPorts): app.Device( sourceNames[port] )['state']['Value'] = 'on' if port == driven else 'off' for wfIndex in range(len(sourceNames)): thiswflist.append( app.Device(sourceNames[wfIndex]).Waveform()) self.wflist.append(thiswflist) for port in range(snp.simulationNumPorts): app.Device( sourceNames[port])['state']['Value'] = stateList[port] self.transferMatriceProcessor = si.td.f.TransferMatricesProcessor( transferMatrices) si.td.wf.Waveform.adaptionStrategy = 'SinX' if SignalIntegrity.App.Preferences[ 'Calculation.UseSinX'] else 'Linear' try: outputwflist = [] for port in range(len(self.wflist)): outputwflist.append( self.transferMatriceProcessor.ProcessWaveforms( self.wflist[port], adaptToLargest=True)) except si.SignalIntegrityException as e: return None # # The list of list of input waveforms have been processed processed, generating a list of list of output waveforms in # self.outputwflist. The names of the output waveforms are in snp.m_sd.pOutputList. # outputwflist = [[ wf.Adapt( si.td.wf.TimeDescriptor(wf.td[wf.td.IndexOfTime(-5e-9)], fd.TimeDescriptor().K, wf.td.Fs)) for wf in driven ] for driven in outputwflist] # The port connection list, which is a list of True or False for each port on the network analyzer, is # converted to a list of network port indices corresponding to the driven ports. # portConnections = [] for pci in range(len(snp.PortConnectionList)): if snp.PortConnectionList[pci]: portConnections.append(pci) outputWaveformList = [] outputWaveformLabels = [] for r in range(len(outputwflist)): wflist = outputwflist[r] for c in range(len(wflist)): wf = wflist[c] wfName = snp.m_sd.pOutputList[c][2] gain = gdoDict[wfName]['gain'] offset = gdoDict[wfName]['offset'] delay = gdoDict[wfName]['delay'] if gain != 1.0 or offset != 0.0 or delay != 0.0: wf = wf.DelayBy(delay) * gain + offset outputWaveformList.append(wf) outputWaveformLabels.append(snp.m_sd.pOutputList[c][2] + str(portConnections[r] + 1)) userSampleRate = SignalIntegrity.App.Project[ 'CalculationProperties.UserSampleRate'] outputWaveformList = [ wf.Adapt( si.td.wf.TimeDescriptor( wf.td.H, int(wf.td.K * userSampleRate / wf.td.Fs), userSampleRate)) for wf in outputWaveformList ] td = si.td.wf.TimeDescriptor( -5e-9, SignalIntegrity.App.Project['CalculationProperties.TimePoints'], SignalIntegrity.App.Project['CalculationProperties.BaseSampleRate'] ) if snp.simulationType != 'CW': # note this matrix is transposed from what is normally expected Vmat = [[ outputWaveformList[outputWaveformLabels.index( 'V' + str(portConnections[r] + 1) + str(portConnections[c] + 1))] for r in range(len(portConnections)) ] for c in range(len(portConnections))] for vli in range(len(Vmat)): tdr = si.m.tdr.TDRWaveformToSParameterConverter( WindowForwardHalfWidthTime=200e-12, WindowReverseHalfWidthTime=200e-12, WindowRaisedCosineDuration=50e-12, Step=(snp.simulationType == 'TDRStep'), Length=0, Denoise=True, DenoisePercent=20., Inverted=False, fd=td.FrequencyList()) tdr.Convert(Vmat[vli], vli) for r in range(len(portConnections)): outputWaveformList.append(tdr.IncidentWaveform if r == vli else si.td.wf.Waveform(td)) outputWaveformLabels.append('A' + str(portConnections[r] + 1) + str(portConnections[vli] + 1)) for r in range(len(portConnections)): outputWaveformList.append(tdr.ReflectWaveforms[r]) outputWaveformLabels.append('B' + str(portConnections[r] + 1) + str(portConnections[vli] + 1)) if not SParameters: return (sourceNames, outputWaveformLabels, transferMatrices, outputWaveformList) else: # waveforms are adapted this way to give the horizontal offset that it already has closest to #-5 ns, with the correct number of points without resampling the waveform in any way. frequencyContentList = [] for wf in outputWaveformList: td = si.td.wf.TimeDescriptor( -5e-9, SignalIntegrity.App. Project['CalculationProperties.TimePoints'], SignalIntegrity.App. Project['CalculationProperties.BaseSampleRate']) td.H = wf.TimeDescriptor()[wf.TimeDescriptor().IndexOfTime( td.H)] fc = wf.Adapt(td).FrequencyContent() frequencyContentList.append(fc) Afc = [[ frequencyContentList[outputWaveformLabels.index( 'A' + str(portConnections[r] + 1) + str(portConnections[c] + 1))] for c in range(len(portConnections)) ] for r in range(len(portConnections))] Bfc = [[ frequencyContentList[outputWaveformLabels.index( 'B' + str(portConnections[r] + 1) + str(portConnections[c] + 1))] for c in range(len(portConnections)) ] for r in range(len(portConnections))] from numpy import array from numpy.linalg import inv frequencyList = td.FrequencyList() data = [None for _ in range(len(frequencyList))] for n in range(len(frequencyList)): B = [[Bfc[r][c][n] for c in range(snp.simulationNumPorts)] for r in range(snp.simulationNumPorts)] A = [[Afc[r][c][n] for c in range(snp.simulationNumPorts)] for r in range(snp.simulationNumPorts)] data[n] = (array(B).dot(inv(array(A)))).tolist() sp = si.sp.SParameters(frequencyList, data) return sp