0

I am trying to create a button in a window that will ultimately run a function that I have written from code. My GUI code so far is as follows:

import sys
from PyQt4 import QtGui, QtCore

class PAINSFILTER(QtGui.QMainWindow):
def __init__(self):
    QtGui.QWidget.__init__(self)
    # Layout Init.
    self.setGeometry (650, 300, 600, 600)
    self.setWindowTitle('Data Viewer')
    self.setWindowIcon(QtGui.QIcon('pill.png'))

    extractAction = QtGui.QAction("Quit", self)
    extractAction.setShortcut("Ctrl+Q")
    extractAction.setStatusTip('Leave App')
    extractAction.triggered.connect(self.close_application)

    self.statusBar()
    mainMenu = self.menuBar()
    fileMenu = mainMenu.addMenu("&File")
    fileMenu.addAction(extractAction)

    self.uploadButton = QtGui.QPushButton('UPLOAD SDF', self)
    self.runfilterButton = QtGui.QPushButton('Run Filter', self)

    self.uploadButton.move (200, 50)
    self.runfilterButton.move (400,50)
    hBoxLayout = QtGui.QHBoxLayout()

    hBoxLayout.addWidget(self.uploadButton)
    hBoxLayout.addWidget(self.runfilterButton)
    self.setLayout(hBoxLayout)
    # Signal Init.
    self.connect(self.uploadButton, QtCore.SIGNAL('clicked()'), self.open)

def open (self):
    filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
    print 'Path file:', filename

def close_application(self):
    print ("Out")
    sys.exit()






def run():
    app = QtGui.QApplication(sys.argv)
    mw = PAINSFILTER()
    mw.show()
    sys.exit(app.exec_())

    run()

The function I am trying to run through the button is a simple nested loop that will take the file I uploaded through the "upload sdf" button and run it through that function. How do I link that function to a button using PyQt. Here is the function for reference:

suppl = Chem.SDMolSupplier('data.sdf') #this .sdf file is the one uploaded through the upload sdf button
for m in suppl:
for x in range(len(pains_smarts)):
    if m.HasSubstructMatch(Chem.MolFromSmarts(pains_smarts[x])):
        match+=1
        has_pains.append(m)
        ss.append(c)
    else:
        no_match+=1
c+=1

for m in suppl:
for x in range(len(pains_smarts)):
    if m.HasSubstructMatch(Chem.MolFromSmarts(pains_smarts[x])):
        pname.append(pains_name[x])

for m in suppl:
for x in range(len(pains_smarts)):
    if m.HasSubstructMatch(Chem.MolFromSmarts(pains_smarts[x])):
        psmarts.append(pains_smarts[x])

uniquess = set(ss)


w = Chem.SDWriter('pains_structures.sdf')
notpains = Chem.SDWriter('no_pains_structures.sdf')
temp = 0

for m in suppl:
if temp in uniquess:
    w.write(m)
else:
    notpains.write(m)
temp += 1

w.flush()
notpains.flush()


import csv
csv_out = open("pains_compounds.csv", "w")
mywriter = csv.writer(csv_out)

for row in zip(ss, psmarts, pname):
mywriter.writerow(row)

csv_out.close()

new_suppl = Chem.SDMolSupplier("pains_structures.sdf")
ms = [x for x in new_suppl if x is not None]
for m in ms: tmp = AllChem.Compute2DCoords(m)
from rdkit.Chem import Draw
img = Draw.MolsToGridImage(ms, molsPerRow = 6, subImgSize = (200, 200),         legends = [x.GetProp("ID") for x in ms])
img.save("pains_img.png")
olanre
  • 31
  • 1
  • 1
  • 4
  • Could you explain what you have tried and why it hasn't worked? Have you tried sticking the second lot of code in the `open` method after getting the filename and using `suppl = Chem.SDMolSupplier(filename)`? – three_pineapples Jul 28 '15 at 09:51

1 Answers1

0

Take a look at the PyQt signaling functionality. For a QPushButton in particular it becomes:

 buttonName.clicked.connect(functionName)

Whenever a button is clicked, it will emit the signal clicked which now has functionName registered to execute. n.b. you do not put parentheses after the functionName as you do not want the function to execute, but rather pass the function itself. Additionally the function needs to satisfy the output of the clicked signal, which emits a boolean (so functionName needs to take in that argument). In your case, since you want to pass another object, you can make a method:

def clickHandler(self,checked):
    #call function with object to pass as argument here

which calls your method and takes in the object you want to pass

csunday95
  • 1,279
  • 10
  • 18
  • 1
    FYI, PyQt does some magic and your function is allowed to have less arguments than the signal (so `clickHandler(self)` works too). I can't seem to find the documentation which details this though, but you can try it and see that it is true! – three_pineapples Jul 28 '15 at 07:10
  • 1
    Also, It looks like this might not answer the question. On a second reading (I made the same original interpretation you did) they have already connected the button to a slot which opens a file selection dialog. They seems to want to know how to use the filename returned from that in their other code... – three_pineapples Jul 28 '15 at 07:13
  • Right, now to use the filename returned from that in the other code is the main problem. – olanre Jul 29 '15 at 14:53