def generate_netlist(): netlist_path = os.path.join(path, netlist_name + '.net') netlist = Netlist(netlist_path, clear=True) netlist_line = {'dictionary': 'pwl', 'component': 'storage', 'label': 'stor', 'arguments': {'file': repr(data_path), 'ctrl': 'e', 'integ': True}, 'nodes': ('N1', 'N2')} netlist.add_line(netlist_line) netlist_line = {'dictionary': 'pwl', 'component': 'dissipative', 'label': 'diss', 'arguments': {'file': repr(data_path), 'ctrl': 'f'}, 'nodes': (datum, 'N1')} netlist.add_line(netlist_line) netlist_line = {'dictionary': 'electronics', 'component': 'source', 'label': 'IN', 'arguments': {'type': 'voltage', 'ctrl': 'f'}, 'nodes': (datum, 'N2')} netlist.add_line(netlist_line) netlist.write()
def test_faust_fx_generation(): path = os.path.join(here, 'lowpass.net') # Absolute path netlist = Netlist(path) # Init Netlist with path to '.net' file #print(netlist.netlist()) # print netlist content graph = netlist.to_graph() # Build Graph object from netlist core = graph.to_core() # perform graph analysis and produce `Core`object #core.pprint() # show structure core.M, core.J(), core.R() core.reduce_z() # reduce linear dissipation functions in matrix R #core.pprint() # show structure core.M, core.J(), core.R() pfc, C, R1 = core.symbols(['pfc', 'CCapa', 'R1']) # define some symbols fref = 20 cutoff = fref*10**(3*pfc) # pfc in [0, 1] => cutoff in [2e1, 2e4] rc = 1/(2*3.14157*cutoff*C) # resistance = 1/(2*pi*cutoff*C) # 1 remplacer core.subs[R1] = rc # substitute symbol R1 by expression rc # 2 appliquer core.substitute(selfexprs=True) # substitute symbols by expressions core.R() # 3 déclarer core.add_parameters(pfc) # add pfc to the list of control parameters # path to generated .dsp file label = 'lowpass' dsppath = os.path.join(here, label+'.dsp') # Select inputs: list of constant values and input labels # Here, we select input as 'uI' and set 'uO' to constant 0 inputs = (0., 'uI') # Select outputs: list of outputs labels outputs = ('yO', ) from pyphs import core2faustfx core2faustfx(core, path=dsppath, inputs=inputs, outputs=outputs) os.remove(dsppath) return True
def test_faust_fx_generation(): path = os.path.join(here, 'lowpass.net') # Absolute path netlist = Netlist(path) # Init Netlist with path to '.net' file #print(netlist.netlist()) # print netlist content graph = netlist.to_graph() # Build Graph object from netlist core = graph.to_core() # perform graph analysis and produce `Core`object #core.pprint() # show structure core.M, core.J(), core.R() core.reduce_z() # reduce linear dissipation functions in matrix R #core.pprint() # show structure core.M, core.J(), core.R() pfc, C, R1 = core.symbols(['pfc', 'CCapa', 'R1']) # define some symbols fref = 20 cutoff = fref * 10**(3 * pfc) # pfc in [0, 1] => cutoff in [2e1, 2e4] rc = 1 / (2 * 3.14157 * cutoff * C) # resistance = 1/(2*pi*cutoff*C) # 1 remplacer core.subs[R1] = rc # substitute symbol R1 by expression rc # 2 appliquer core.substitute(selfexprs=True) # substitute symbols by expressions core.R() # 3 déclarer core.add_parameters(pfc) # add pfc to the list of control parameters # path to generated .dsp file label = 'lowpass' dsppath = os.path.join(here, label + '.dsp') # Select inputs: list of constant values and input labels # Here, we select input as 'uI' and set 'uO' to constant 0 inputs = (0., 'uI') # Select outputs: list of outputs labels outputs = ('yO', ) from pyphs import core2faustfx core2faustfx(core, path=dsppath, inputs=inputs, outputs=outputs) os.remove(dsppath) return True
def _read(self): if not os.path.exists(self.path): self.netlist = Netlist(self.path) if not hasattr(self, 'Netlist'): self.netlist = Netlist(self.path) else: self.netlist.path = self.path for n in range(self.netlist.nlines()): self.netlist.delline(0) self.netlist.read() self.update() self._change_status(True) self.initSig.sig.emit()
def generate_netlist(): netlist_path = os.path.join(path, netlist_name + '.net') netlist = Netlist(netlist_path, clear=True) netlist_line = { 'dictionary': 'pwl', 'component': 'storage', 'label': 'stor', 'arguments': { 'file': repr(data_path), 'ctrl': 'e', 'integ': True }, 'nodes': ('N1', 'N2') } netlist.add_line(netlist_line) netlist_line = { 'dictionary': 'pwl', 'component': 'dissipative', 'label': 'diss', 'arguments': { 'file': repr(data_path), 'ctrl': 'f' }, 'nodes': (datum, 'N1') } netlist.add_line(netlist_line) netlist_line = { 'dictionary': 'electronics', 'component': 'source', 'label': 'IN', 'arguments': { 'type': 'voltage', 'ctrl': 'f' }, 'nodes': (datum, 'N2') } netlist.add_line(netlist_line) netlist.write()
# ----------------------------- CORES ------------------------------------- # this_script = os.path.realpath(__file__) here = this_script[:this_script.rfind(os.sep)] def netlist_path(label): return here + os.sep + label + '.net' def sort_outputs(core): for i in range(core.dims.y()): if not str(core.y[i]).endswith(str(i+1)): core.move_port([str(y).endswith(str(i+1)) for y in core.y].index(True), i) # build simple Cores net1 = Netlist(netlist_path('phs1')) c1 = net1.to_core() sort_outputs(c1) net2 = Netlist(netlist_path('phs2')) c2 = net2.to_core() sort_outputs(c2) # concatenate c1 and c2 into a new Core core = c1 + c2 # define the connection core.add_connector((core.y.index(c1.y[1]), core.y.index(c2.y[1])), alpha=1) # apply the connection core.connect()
@author: Falaize """ from __future__ import absolute_import, division, print_function import os from pyphs import Netlist, Graph label = 'triodeamp' path = os.path.realpath(__file__)[:os.path.realpath(__file__).rfind(os.sep)] netlist_filename = path + os.sep + label + '.net' netlist = Netlist(netlist_filename) graph = Graph(netlist=netlist) core = graph.to_core(verbose=False) core.linear_nonlinear() core.subsinverse() #core.reduce_z() #if __name__ == '__main__': # # from pyphs import signalgenerator # # config = {'fs': 96e3, # 'split': True,
Created on Sat May 13 17:00:14 2017 @author: Falaize """ from __future__ import absolute_import, division, print_function import os from pyphs import Netlist label = 'fractional_integrator_fc' path = os.path.realpath(__file__)[:os.path.realpath(__file__).rfind(os.sep)] netlist_filename = path + os.sep + label + '.net' netlist = Netlist(netlist_filename) core = netlist.to_core() # %% ------------------------------ SIMULATION ------------------------------ # # UNCOMMENT BELOW FOR SIMULATION and PLOT OF TRANSFER FUNCTION # !!! Very long simulation with numpy (use c++ if possible) #if __name__ == '__main__': # from pyphs import Simulation, signalgenerator # from pyphs.misc.signals.analysis import transferFunction # import matplotlib.pyplot as plt # import numpy as np # # config = {'fs': 48e3,
def NetlistThieleSmallNL(clear=True, R=1e3, L=5e-2, Bl=50, M=0.1, K=5e3, A=1): """ Write the netlist for a nonlinear version of the thieleSmall modeling of \ loudspeakers. """ netlist = Netlist(path, clear=clear) datum = netlist.datum # input voltage source = { 'dictionary': 'electronics', 'component': 'source', 'label': 'IN', 'nodes': ('A', datum), 'arguments': { 'type': "voltage" } } netlist.add_line(source) # resistor 1 resistance = { 'dictionary': 'electronics', 'component': 'resistor', 'label': 'R', 'nodes': ('A', 'B'), 'arguments': { 'R': ('R', R) } } netlist.add_line(resistance) # inductor inductor = { 'dictionary': 'electronics', 'component': 'inductor', 'label': 'L', 'nodes': ('B', 'C'), 'arguments': { 'L': ('L', L) } } netlist.add_line(inductor) # gyrator gyrator = { 'dictionary': 'connectors', 'component': 'gyrator', 'label': 'G', 'nodes': ('C', datum, 'D', datum), 'arguments': { 'alpha': ('Bl', Bl) } } netlist.add_line(gyrator) # masse mass = { 'dictionary': 'mechanics_dual', 'component': 'mass', 'label': 'M', 'nodes': ('D', 'E'), 'arguments': { 'M': ('M', M) } } netlist.add_line(mass) # ressort cubic stifness = { 'dictionary': 'mechanics_dual', 'component': 'springcubic', 'label': 'K', 'nodes': ('E', 'F'), 'arguments': { 'K0': ('K0', K), 'K2': ('K2', 1e20) } } netlist.add_line(stifness) # amortissement damper = { 'dictionary': 'mechanics_dual', 'component': 'damper', 'label': 'A', 'nodes': ('F', datum), 'arguments': { 'A': ('A', A) } } netlist.add_line(damper) netlist.write() return netlist
# electronics.resistor R1 ('A', 'B'): R=('R1', 1000.0); # electronics.inductor L1 ('B', 'C'): L=('L1', 0.05); # electronics.capacitor C1 ('C', 'ref'): C=('C1', 2e-06); # ``` # # Automated netlist generation # There is two reasons you want to automatize the generation of the netlist: # 1. It allows for easy management of sequential experiments (*e.g.* for which a single parameter take several values). # 2. It is more robust with respect to possible changes of the netlist formating in the future of `pyphs`. # # This is done by defining each component as a line of the netlist in the `pyphs.Netlist`. This structure is defined by the `pyphs.graphs.Netlist` class, and is accessible with # In[2]: from pyphs import Netlist net = Netlist('rlc.net', clear = True) # Each line is defined with the `phs.graph.netlist.add_line` command, which takes python dicitonary with the following structure as arguments: # ```python # netlist_line = {'dictionary': 'dico', # 'component': 'comp', # 'label': 'label', # 'nodes': ('node1', ..., 'nodeN'), # 'arguments': {'par1': "('lab1', val1)", # 'par2': "'lab2'", # 'par3': "val3" # } # } # ``` # As an example, the declaration of the RLC components to the above `phs` object is as follows.
Created on Sat May 13 17:00:14 2017 @author: Falaize """ from __future__ import absolute_import, division, print_function import os from pyphs import Netlist label = 'fractional_intergrator_ec' path = os.path.realpath(__file__)[:os.path.realpath(__file__).rfind(os.sep)] netlist_filename = path + os.sep + label + '.net' netlist = Netlist(netlist_filename) core = netlist.to_core() # UNCOMMENT BELOW FOR SIMULATION and PLOT OF TRANSFER FUNCTION # !!! Very long simulation with numpy # #if __name__ == '__main__': # # from pyphs import Simulation, signalgenerator # from pyphs.misc.signals.analysis import transferFunction # import matplotlib.pyplot as plt # import numpy as np # # config = {'fs': 48e3, # 'split': True, # 'pbar': True, # 'timer': True,
""" return here + os.sep + label + '.net' def sort_outputs(core): """ Build netlist file name from label. """ for i in range(core.dims.y()): if not str(core.y[i]).endswith(str(i + 1)): core.move_port([str(y).endswith(str(i + 1)) for y in core.y].index(True), i) # build simple Cores net1 = Netlist(netlist_path('phs1')) c1 = net1.to_core() sort_outputs(c1) net2 = Netlist(netlist_path('phs2')) c2 = net2.to_core() sort_outputs(c2) # ----------------------------- CONNECT ----------------------------------- # # concatenate c1 and c2 into a new Core core = c1 + c2 # define the connection core.add_connector((core.y.index(c1.y[1]), core.y.index(c2.y[1])), alpha=1)
@author: afalaize """ from __future__ import absolute_import, division, print_function import os from pyphs import Netlist import matplotlib.pyplot as plt plt.close('all') # netlist is "{label}.net" label = 'sp_circuit' # get folder path path = os.path.realpath(__file__)[:os.path.realpath(__file__).rfind(os.sep)] # def filename netlist_filename = os.path.join(path, '{0}.net'.format(label)) # read in Netlist object netlist = Netlist(netlist_filename) # Build Graph object graph = netlist.to_graph() graph.sp_split() # Build Core object core = graph.to_core(merge_all=True)
# electronics.resistor R1 ('A', 'B'): R=('R1', 1000.0); # electronics.inductor L1 ('B', 'C'): L=('L1', 0.05); # electronics.capacitor C1 ('C', 'ref'): C=('C1', 2e-06); # ``` # # Automated netlist generation # There is two reasons you want to automatize the generation of the netlist: # 1. It allows for easy management of sequential experiments (*e.g.* for which a single parameter take several values). # 2. It is more robust with respect to possible changes of the netlist formating in the future of `pyphs`. # # This is done by defining each component as a line of the netlist in the `pyphs.Netlist`. This structure is defined by the `pyphs.graphs.Netlist` class, and is accessible with # In[2]: from pyphs import Netlist net = Netlist('rlc.net', clear = True) # Each line is defined with the `phs.graph.netlist.add_line` command, which takes python dicitonary with the following structure as arguments: # ```python # netlist_line = {'dictionary': 'dico', # 'component': 'comp', # 'label': 'label', # 'nodes': ('node1', ..., 'nodeN'), # 'arguments': {'par1': "('lab1', val1)", # 'par2': "'lab2'", # 'par3': "val3" # } # } # ``` # As an example, the declaration of the RLC components to the above `phs` object is as follows.
def NetlistThieleSmallNL(clear=True, R=1e3, L=5e-2, Bl=50, M=0.1, K=5e3, A=1): """ Write the netlist for a nonlinear version of the thieleSmall modeling of \ loudspeakers. """ netlist = Netlist(path, clear=clear) datum = netlist.datum # input voltage source = {'dictionary': 'electronics', 'component': 'source', 'label': 'IN', 'nodes': ('A', datum), 'arguments': {'type': "voltage"}} netlist.add_line(source) # resistor 1 resistance = {'dictionary': 'electronics', 'component': 'resistor', 'label': 'R', 'nodes': ('A', 'B'), 'arguments': {'R': ('R', R)}} netlist.add_line(resistance) # inductor inductor = {'dictionary': 'electronics', 'component': 'inductor', 'label': 'L', 'nodes': ('B', 'C'), 'arguments': {'L': ('L', L)}} netlist.add_line(inductor) # gyrator gyrator = {'dictionary': 'connectors', 'component': 'gyrator', 'label': 'G', 'nodes': ('C', datum, 'D', datum), 'arguments': {'alpha': ('Bl', Bl)}} netlist.add_line(gyrator) # masse mass = {'dictionary': 'mechanics_dual', 'component': 'mass', 'label': 'M', 'nodes': ('D', 'E'), 'arguments': {'M': ('M', M)}} netlist.add_line(mass) # ressort cubic stifness = {'dictionary': 'mechanics_dual', 'component': 'springcubic', 'label': 'K', 'nodes': ('E', 'F'), 'arguments': {'K0': ('K0', K), 'K2': ('K2', 1e20)} } netlist.add_line(stifness) # amortissement damper = {'dictionary': 'mechanics_dual', 'component': 'damper', 'label': 'A', 'nodes': ('F', datum), 'arguments': {'A': ('A', A)}} netlist.add_line(damper) netlist.write() return netlist
class NetlistWidget(QWidget): def get_status(self): return self.titleWidget.status status = property(get_status) def get_label(self): fn = self.netlist.filename label = fn[:fn.rfind('.')] return label label = property(get_label) def __init__(self, filepath=None, parent=None): super(NetlistWidget, self).__init__(parent) self.initSig = NoneSig() self.statusSig = BoolSig() self.initUI() if filepath is None: self.initMessage() else: self.path = filepath self._read() def initUI(self): # --------------------------------------------------------------------- # Create Empty (nlines)x5 Table self.tableWidget = QTableWidget() self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableWidget.setColumnCount(5) self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableLabels = ('Dictionary', 'Component', 'Label', 'Nodes', 'Arguments') # Add Header horHeaders = [] for n, key in enumerate(self.tableLabels): horHeaders.append(key) self.tableWidget.setHorizontalHeaderLabels(horHeaders) self.tableWidget.setFixedWidth(520) self.tableWidget.setFixedHeight(200) # --------------------------------------------------------------------- # Define Netlist File Actions self.buttonsLayout = QHBoxLayout() # New Action new_icon = QIcon(os.path.join(iconspath, 'new.png')) self.newAction = QAction(new_icon, '&New Netlist', self) self.newAction.setShortcut('Ctrl+N') self.newAction.setStatusTip('Create a new netlist') self.newAction.triggered.connect(self._new) self.newButton = QPushButton(new_icon, '') self.newButton.setToolTip('Create a new netlist') self.newButton.clicked.connect(self._new) self.buttonsLayout.addWidget(self.newButton) # Open Action open_icon = QIcon(os.path.join(iconspath, 'open.png')) self.openAction = QAction(open_icon, '&Open Netlist', self) self.openAction.setShortcut('Ctrl+O') self.openAction.setStatusTip('Open an existing netlist') self.openAction.triggered.connect(self._open) self.openButton = QPushButton(open_icon, '') self.openButton.setToolTip('Open an existing netlist') self.openButton.clicked.connect(self._open) self.buttonsLayout.addWidget(self.openButton) # Save Action save_icon = QIcon(os.path.join(iconspath, 'save.png')) self.saveAction = QAction(save_icon, '&Save Netlist', self) self.saveAction.setShortcut('Ctrl+S') self.saveAction.setStatusTip('Save the netlist') self.saveAction.triggered.connect(self._save) self.saveButton = QPushButton(save_icon, '') self.saveButton.setToolTip('Save the netlist') self.saveButton.clicked.connect(self._save) self.buttonsLayout.addWidget(self.saveButton) # Saveas Action saveas_icon = QIcon(os.path.join(iconspath, 'saveas.png')) self.saveasAction = QAction(saveas_icon, '&Save Netlist as', self) self.saveasAction.setShortcut('Ctrl+Shift+S') self.saveasAction.setStatusTip('Save as a new netlist') self.saveasAction.triggered.connect(self._saveas) self.saveasButton = QPushButton(saveas_icon, '') self.saveasButton.setToolTip('Save the netlist as a new netlist') self.saveasButton.clicked.connect(self._saveas) self.buttonsLayout.addWidget(self.saveasButton) # --------------------------------------------------------------------- # Define Netlist Line Actions self.actionsLayout = QHBoxLayout() # Editline Action edit_icon = QIcon(os.path.join(iconspath, 'edit.png')) self.editAction = QAction(edit_icon, '&Edit line', self) self.editAction.setShortcut('Ctrl+E') self.editAction.setStatusTip('Edit an existing line of the netlist') self.editAction.triggered.connect(self._edit_line) self.editButton = QPushButton(edit_icon, '') self.editButton.setToolTip('Edit an existing line of the netlist') self.editButton.clicked.connect(self._edit_line) self.actionsLayout.addWidget(self.editButton) # addline Action add_icon = QIcon(os.path.join(iconspath, 'add.png')) self.addlineAction = QAction(add_icon, '&New line', self) self.addlineAction.setShortcut('Ctrl+L') self.addlineAction.setStatusTip('Add a new line to the netlist') self.addlineAction.triggered.connect(self._new_line) self.addlineButton = QPushButton(add_icon, '') self.addlineButton.setToolTip('Add a new line to the netlist') self.addlineButton.clicked.connect(self._new_line) self.actionsLayout.addWidget(self.addlineButton) # delline Action del_icon = QIcon(os.path.join(iconspath, 'del.png')) self.dellineAction = QAction(del_icon, '&Delete line', self) self.dellineAction.setShortcut('Ctrl+L') self.dellineAction.setStatusTip('Delete a line from the netlist') self.dellineAction.triggered.connect(self._del_line) self.dellineButton = QPushButton(del_icon, '') self.dellineButton.setToolTip('Delete a line from the netlist') self.dellineButton.clicked.connect(self._del_line) self.actionsLayout.addWidget(self.dellineButton) self.actionsLayout.addStretch() # --------------------------------------------------------------------- # Datum widget desc = 'Key for reference node (e.g. electrical grounds and mechanical reference points).' self.datumWidget = DescriptionWidget('datum', datum, desc) # self.actionsLayout.addWidget(datumWidget) # # self.actionsWidget = QWidget(self) # self.actionsWidget.setLayout(self.actionsLayout) # --------------------------------------------------------------------- # title widget title = 'NETLIST' self.labelWidget = QLabel(self) status_labels = {True: 'Saved', False: 'Not Saved'} self.titleWidget = TitleWidget(title=title, labelWidget=self.labelWidget, status_labels=status_labels, buttonsLayout=self.buttonsLayout) self.tableWidget.setMaximumWidth(self.titleWidget.width()) def initMessage(self): msgBox = QMessageBox(self) msgBox.setText('Netlist file selection') msgBox.addButton(QPushButton('New'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Open'), QMessageBox.NoRole) init = msgBox.exec_() if init == 0: self._new() else: assert init == 1 self._open() def update(self): # read data data = dict() for label in self.tableLabels: data.update({label: list()}) for netline in self.netlist: for label in self.tableLabels: el = netline[label.lower()] if isinstance(el, dict): string = '' for k in el.keys(): string += "{0!s}: {1!s}; ".format(k, el[k]) string = string[:-1] elif isinstance(el, tuple): string = '' for obj in el: string += "{0!s}, ".format(obj) string = string[:-1] else: string = str(el) data[label].append(string) # Enter data onto Table self.tableWidget.setRowCount(self.netlist.nlines()) for n, key in enumerate(self.tableLabels): for m, item in enumerate(data[key]): newitem = QTableWidgetItem(item) self.tableWidget.setItem(m, n, newitem) self._update_path() self._change_status(False) def _change_status(self, s=False): if not self.status == s: self.titleWidget._change_status(s) self.statusSig.sig.emit(s) def _update_path(self): label = self.netlist.filename self.titleWidget.labelWidget.setToolTip(self.netlist.path) self.titleWidget._change_label(label) def _read(self): if not os.path.exists(self.path): self.netlist = Netlist(self.path) if not hasattr(self, 'Netlist'): self.netlist = Netlist(self.path) else: self.netlist.path = self.path for n in range(self.netlist.nlines()): self.netlist.delline(0) self.netlist.read() self.update() self._change_status(True) self.initSig.sig.emit() def _new(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog dialog = QFileDialog() try: filename = os.path.join(self.netlist.path) except AttributeError: filename = os.path.join(os.getcwd(), 'netlist.net') dialog.selectFile(filename) fname, _ = dialog.getSaveFileName( self, "Save new netlist file as...", filename, "All Files (*);;PyPHS netlist files (*.net)", "PyPHS netlist files (*.net)", options=options) if not fname == '': if not fname[-4:] == '.net': fname += '.net' self.path = fname self._read() def _open(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog dialog = QFileDialog() try: filename = os.path.join(self.netlist.path) except AttributeError: filename = os.path.join(os.getcwd(), 'netlist.net') dialog.selectFile(filename) fname, _ = dialog.getOpenFileName( self, 'Open netlist file', filename, "All Files (*);;PyPHS netlist files (*.net)", "PyPHS netlist files (*.net)", options=options) if not fname == '': self.path = fname self._read() def _saveas(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog dialog = QFileDialog() try: filename = os.path.join(self.netlist.path) except AttributeError: filename = os.path.join(os.getcwd(), 'netlist.net') dialog.selectFile(filename) fname, _ = dialog.getSaveFileName( self, "Save netlist file as...", filename, "All Files (*);;PyPHS netlist files (*.net)", "PyPHS netlist files (*.net)", options=options) if not fname == '': if not fname[-4:] == '.net': fname += '.net' self.netlist.write(fname) self.path = fname self._read() def _save(self): self.netlist.write() self._change_status(True) def _new_line(self): netline, res = EditDialog.getNetline(self) if res: self.netlist.add_line(netline) self.update() def _del_line(self): for i in range(self.tableWidget.rowCount()): r = range(self.tableWidget.columnCount()) if any([self.tableWidget.item(i, j).isSelected() for j in r]): break self.netlist.delline(i) self.update() def _edit_line(self): for i in range(self.tableWidget.rowCount()): r = range(self.tableWidget.columnCount()) if any([self.tableWidget.item(i, j).isSelected() for j in r]): break line = self.netlist[i] netline, res = EditDialog.getNetline(self, line) if res: self.netlist.setline(i, netline) self.update()