def __init__(self, app, system, freq=30): self.system = system self.on_update_gui = Signal() self.frq = freq self.app = app self.on_run_started = Signal() self.on_run_finished = Signal()
def __init__(self, parent=None): super(NEBWidget, self).__init__(parent=parent) self.ui = ui.nebbrowser.Ui_Form() self.ui.setupUi(self) self.plw = self.ui.widget # self.plw.axes.set_ylabel("NEB image energy") # pl.xlabel("distance along the path") # self.system = system # self.min1 = min1 # self.min2 = min2 # self.minimum_selected = Signal() # self.minimum_selected(minim) #the function which tells the eventloop to continue processing events #if this is not set, the plots will stall and not show until the end of the NEB run. #ideally it is the function app.processEvents where app is returned by #app = QApplication(sys.argv) self.process_events = Signal() self.on_neb_pick = Signal() self.on_neb_pick.connect(self.on_pick)
class BHRunner(QtCore.QObject): """manage a single basinhopping run in a separate process This class spawns the basinhopping job in a separate process and receives the minima found through a pipe """ def __init__(self, system, database, nsteps=None, on_finish=None): QtCore.QObject.__init__(self) self.system = system self.database = database self.daemon = True self.nsteps = nsteps #child_conn = self self.bhprocess = None self.on_finish = Signal() if on_finish is not None: self.on_finish.connect(on_finish) def is_alive(self): return self.bhprocess.is_alive() def poll(self): if not self.parent_conn.poll(): if not self.bhprocess.is_alive(): self.refresh_timer.stop() self.on_finish() return return minimum = self.parent_conn.recv() self.database.addMinimum(minimum[0], minimum[1]) def start(self): if self.bhprocess: if self.bhprocess.is_alive(): return parent_conn, child_conn = mp.Pipe() self.bhprocess = _BHProcess(self.system, child_conn, nsteps=self.nsteps) self.bhprocess.daemon = self.daemon self.bhprocess.start() self.parent_conn = parent_conn self.refresh_timer = QtCore.QTimer() self.refresh_timer.timeout.connect(self.poll) self.refresh_timer.start(50.) # time in msec def kill(self): """kill the job that is running""" if self.is_alive(): self.parent_conn.send("kill") self.bhprocess.join()
def __init__(self, system, database, on_number_alive_changed=None): self.system = system self.database = database self.workers = [] self._old_nalive = -1 self.on_number_alive_changed = Signal() if on_number_alive_changed is not None: self.on_number_alive_changed.connect(on_number_alive_changed) self.refresh_timer = QtCore.QTimer() self.refresh_timer.timeout.connect(self._check_number)
class BHRunner(QtCore.QObject): """manage a single basinhopping run in a separate process This class spawns the basinhopping job in a separate process and receives the minima found through a pipe """ def __init__(self, system, database, nsteps=None, on_finish=None): QtCore.QObject.__init__(self) self.system = system self.database = database self.daemon = True self.nsteps = nsteps #child_conn = self self.bhprocess = None self.on_finish = Signal() if on_finish is not None: self.on_finish.connect(on_finish) def is_alive(self): return self.bhprocess.is_alive() def poll(self): if not self.parent_conn.poll(): if not self.bhprocess.is_alive(): self.refresh_timer.stop() self.on_finish return return minimum = self.parent_conn.recv() self.database.addMinimum(minimum[0],minimum[1]) def start(self): if(self.bhprocess): if(self.bhprocess.is_alive()): return parent_conn, child_conn = mp.Pipe() self.bhprocess = _BHProcess(self.system, child_conn, nsteps=self.nsteps) self.bhprocess.daemon = self.daemon self.bhprocess.start() self.parent_conn = parent_conn self.refresh_timer = QtCore.QTimer() self.refresh_timer.timeout.connect(self.poll) self.refresh_timer.start(50.) # time in msec def kill(self): """kill the job that is running""" if self.is_alive(): self.parent_conn.send("kill") self.bhprocess.join()
def __init__(self, system, database, nsteps=None, on_finish=None): QtCore.QObject.__init__(self) self.system = system self.database = database self.daemon = True self.nsteps = nsteps #child_conn = self self.bhprocess = None self.on_finish = Signal() if on_finish is not None: self.on_finish.connect(on_finish)
def __init__(self, database, graph=None, params=None, parent=None): if params is None: params = dict() super(DGraphWidget, self).__init__(parent=parent) self.database = database self.graph = graph self.ui = dgraph_browser.Ui_Form() self.ui.setupUi(self) self.canvas = self.ui.widget.canvas # self.ui.wgt_mpl_toolbar = NavigationToolbar() # self.toolbar = self. self.input_params = params.copy() self.params = {} self.set_defaults() self.minimum_selected = Signal() # self.minimum_selected(minim) self._selected_minimum = None # self.rebuild_disconnectivity_graph() self.colour_tree = [] self.tree_selected = None self._tree_cid = None self._minima_cid = None self._minima_labels = dict()
def __init__(self, system, database, min1, min2, outstream=None, return_smoothed_path=True, daemon=True): QtCore.QObject.__init__(self) self.system = system self.database = database self.min1, self.min2 = min1, min2 self.return_smoothed_path = return_smoothed_path self.daemon = daemon self.outstream = outstream self.on_finished = Signal() self.decprocess = None self.newminima = set() self.newtransition_states = set() self.success = False self.killed_early = False self.is_running = False
def __init__(self, app, systemtype, parent=None): QtGui.QWidget.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.systemtype = systemtype self.transition = None self.app = app self.double_ended_connect_runs = [] self.pick_count = 0 self.minima_selection = MySelection() self.on_minimum_1_selected = Signal() self.on_minimum_2_selected = Signal() # set up the list manager self.list_manager = ListViewManager(self) # define the system self.NewSystem() # finish setting up the list manager (this must be done after NewSystem() is called) self.list_manager.finish_setup() # try to load the pymol viewer. try: self.usepymol = self.system.params.gui.use_pymol except (KeyError, AttributeError): self.usepymol = config.getboolean("gui", "use_pymol") if self.usepymol: try: from pymol_viewer import PymolViewer self.pymolviewer = PymolViewer(self.system.load_coords_pymol) except (ImportError or NotImplementedError): self.usepymol = False if self.usepymol == False: # note: glutInit() must be called exactly once. pymol calls it # during pymol.finish_launching(), so if we call it again it will # give an error. On the other hand, if we're not using pymol we # must call it. from OpenGL.GLUT import glutInit glutInit() self.bhmanager = None
def __init__(self, plw, axes, neb=None, frq=30, nplots=3): self.count = 0 self.nplots = nplots self.data = deque() self.frq = frq self.process_events = Signal() self.plw = plw self.axes = axes self.neb = neb self.on_coords_select = Signal() self.points_list = [] def on_pick_tmp(event): self.on_pick(event) return self.plw.mpl_connect('pick_event', on_pick_tmp)
class BHManager(object): def __init__(self, system, database, on_number_alive_changed=None): self.system = system self.database = database self.workers = [] self._old_nalive = -1 self.on_number_alive_changed = Signal() if on_number_alive_changed is not None: self.on_number_alive_changed.connect(on_number_alive_changed) self.refresh_timer = QtCore.QTimer() self.refresh_timer.timeout.connect(self._check_number) def _remove_dead(self): self.workers = [w for w in self.workers if w.is_alive()] if self._old_nalive != len(self.workers): self._old_nalive = len(self.workers) self.on_number_alive_changed(len(self.workers)) def _check_number(self): self._remove_dead() if len(self.workers) == 0: self.refresh_timer.stop() def start_worker(self, nsteps=None): self._remove_dead() worker = BHRunner(self.system, self.database, nsteps=nsteps) worker.on_finish.connect(self._remove_dead) worker.start() self.workers.append(worker) if not self.refresh_timer.isActive(): self.refresh_timer.start(1000.) # time in msec def kill_all_workers(self): for worker in self.workers: worker.kill() def number_of_workers(self): self._remove_dead() return len(self.workers)
def __init__(self, app, systemtype, parent=None): QtGui.QWidget.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.systemtype = systemtype self.transition = None self.app = app self.double_ended_connect_runs = [] self.pick_count = 0 self.minima_selection = MySelection() self.on_minimum_1_selected = Signal() self.on_minimum_2_selected = Signal() # set up the list manager self.list_manager = ListViewManager(self) # define the system self.NewSystem() # finish setting up the list manager (this must be done after NewSystem() is called) self.list_manager.finish_setup() # try to load the pymol viewer. try: self.usepymol = self.system.params.gui.use_pymol except (KeyError, AttributeError): self.usepymol = config.getboolean("gui", "use_pymol") if self.usepymol: try: from .pymol_viewer import PymolViewer self.pymolviewer = PymolViewer(self.system.load_coords_pymol) except (ImportError or NotImplementedError): self.usepymol = False if not self.usepymol: # note: glutInit() must be called exactly once. pymol calls it # during pymol.finish_launching(), so if we call it again it will # give an error. On the other hand, if we're not using pymol we # must call it. from OpenGL.GLUT import glutInit glutInit() self.bhmanager = None
def __init__(self, potential, coords1, coords2, k=100., max_images=50, image_density=10., iter_density=10., verbose=0, factor=1.05, NEBquenchParams=None, adjustk_freq=0, adjustk_tol=0.1, adjustk_factor=1.05, dneb=True, reinterpolate_tol=0.1, reinterpolate=0, adaptive_nimages=False, adaptive_niter=False, interpolator=interpolate_linear, distance=distance_cart, **kwargs): self.potential = potential self.interpolator = interpolator self.verbose = verbose self.distance = distance self.factor = factor self.max_images = max_images self.min_images = 3 self.image_density = image_density self.iter_density = iter_density self.update_event = Signal() self.coords1 = coords1 self.coords2 = coords2 self.reinterpolate = reinterpolate self.reinterpolate_tol = reinterpolate_tol self._nebclass = NEB self._kwargs = kwargs.copy() self.k = k self.adaptive_images = adaptive_nimages self.adaptive_niter = adaptive_niter self._kwargs["adjustk_freq"] = adjustk_freq self._kwargs["adjustk_tol"] = adjustk_tol self._kwargs["adjustk_factor"] = adjustk_factor self._kwargs["dneb"] = dneb if NEBquenchParams is None: NEBquenchParams = {'tol': 1e-2, 'maxErise': 100.0} self.quenchParams = NEBquenchParams self.prepared = False
def __init__(self, db=":memory:", accuracy=1e-3, connect_string='sqlite:///%s', compareMinima=None, createdb=True): self.accuracy = accuracy self.compareMinima = compareMinima if not os.path.isfile(db) or db == ":memory:": newfile = True if not createdb: raise IOError( "createdb is False, but database does not exist (%s)" % db) else: newfile = False # set up the engine which will manage the backend connection to the database self.engine = create_engine(connect_string % db, echo=verbose) if not newfile and not self._is_pele_database(): raise IOError("existing file (%s) is not a pele database." % db) # set up the tables and check the schema version if newfile: self._set_schema_version() self._check_schema_version() self._update_schema() # self._check_schema_version_and_create_tables(newfile) # set up the session which will manage the frontend connection to the database Session = sessionmaker(bind=self.engine) self.session = Session() # these functions will be called when a minimum or transition state is # added or removed self.on_minimum_added = Signal() self.on_minimum_removed = Signal() self.on_ts_added = Signal() self.on_ts_removed = Signal() self.lock = threading.Lock() self.connection = self.engine.connect()
def __init__(self, *args, **kwargs): super(Show3DWithSlider, self).__init__(*args, **kwargs) self.setMinimumSize(200, 200) self.ui = Ui_show3d_with_slider() self.ui.setupUi(self) self.label = self.ui.label self.label.hide() self.ui.btn_animate.hide() self.ui.btn_animate.setCheckable(True) self.oglwgt = self.ui.oglwgt self.slider = self.ui.slider self.on_frame_updated = Signal() self.animate = False self._animate_dir = 1
def __init__(self, database=None, parent=None, app=None, minima=None): QWidget.__init__(self, parent=parent) self.ui = Ui_Form() self.ui.setupUi(self) self.database = database self.minima = minima self.app = app self.canvas = self.ui.canvas.canvas self.axes = self.canvas.axes self.fig = self.canvas.fig self.on_minima_picked = Signal() self.from_minima = set() self.positions = dict() self.boundary_nodes = set() self._selected_minimum = None self._mpl_cid = None self._minima_color_value = None
class NEBWidget(QWidget): def __init__(self, parent=None): super(NEBWidget, self).__init__(parent=parent) self.ui = ui.nebbrowser.Ui_Form() self.ui.setupUi(self) self.plw = self.ui.widget # self.plw.axes.set_ylabel("NEB image energy") # pl.xlabel("distance along the path") # self.system = system # self.min1 = min1 # self.min2 = min2 # self.minimum_selected = Signal() # self.minimum_selected(minim) #the function which tells the eventloop to continue processing events #if this is not set, the plots will stall and not show until the end of the NEB run. #ideally it is the function app.processEvents where app is returned by #app = QApplication(sys.argv) self.process_events = Signal() self.on_neb_pick = Signal() self.on_neb_pick.connect(self.on_pick) def highlight2(self, x, y): """draw a circle around x, y""" # if hasattr(self, "highlight_circle"): try: self.highlight_circle.remove() except Exception: pass self.highlight_circle=Circle((x, y),radius=0.5, fill=False) self.plw.axes.add_patch(self.highlight_circle) def highlight1(self, x, y): ylim = self.plw.axes.get_ylim() # if hasattr(self, "highlight_line"): try: self.highlight_line.remove() except Exception: pass self.highlight_line = Line2D([x,x],list(ylim), ls='--', c='k') # self.highlight_line.set_data([x,x],list(ylim)) self.plw.axes.add_line(self.highlight_line) # self.plw.axes.plot([x,x], list(ylim), 'k') def highlight(self, index, style=1): """draw a vertical line to highlight a particular point in the neb curve""" if index < 0: #I would like to delete the line here, but I don't know how to do it easily return from matplotlib.lines import Line2D S, energies, tmp = self.neb_callback.data[-1] x = S[index] y = energies[index] if style == 2: self.highlight2(x, y) else: self.highlight1(x, y) self.plw.draw() self.process_events() def on_pick(self, index=None, *args, **kwargs): self.highlight(index) def attach_to_NEB(self, neb): neb_callback = NEBCallback(self.plw, self.plw.axes) self.neb_callback = neb_callback neb_callback.process_events.connect(self.process_events) neb_callback.on_coords_select.connect(self.on_neb_pick) neb.update_event.connect(neb_callback)
class MainGUI(QtGui.QMainWindow): """ this is the main class for the pele gui Parameters ---------- app : the application object returned by QtGui.QApplication() systemtype : system class object the system class """ def __init__(self, app, systemtype, parent=None): QtGui.QWidget.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.systemtype = systemtype self.transition = None self.app = app self.double_ended_connect_runs = [] self.pick_count = 0 self.minima_selection = MySelection() self.on_minimum_1_selected = Signal() self.on_minimum_2_selected = Signal() # set up the list manager self.list_manager = ListViewManager(self) # define the system self.NewSystem() # finish setting up the list manager (this must be done after NewSystem() is called) self.list_manager.finish_setup() # try to load the pymol viewer. try: self.usepymol = self.system.params.gui.use_pymol except (KeyError, AttributeError): self.usepymol = config.getboolean("gui", "use_pymol") if self.usepymol: try: from pymol_viewer import PymolViewer self.pymolviewer = PymolViewer(self.system.load_coords_pymol) except (ImportError or NotImplementedError): self.usepymol = False if self.usepymol == False: # note: glutInit() must be called exactly once. pymol calls it # during pymol.finish_launching(), so if we call it again it will # give an error. On the other hand, if we're not using pymol we # must call it. from OpenGL.GLUT import glutInit glutInit() self.bhmanager = None def NewSystem(self): """ this is called to initialize the system with a database """ self.system = self.systemtype() self.connect_db() def on_action_edit_params_triggered(self, checked=None): if checked is None: return self.paramsdlg = DlgParams(self.system.params) self.paramsdlg.show() def processEvents(self): self.app.processEvents() def on_action_db_connect_triggered(self, checked=None): """ launch a file browser to connect to an existing database """ if checked is None: return filename = QtGui.QFileDialog.getSaveFileName(self, "Select database", ".") if len(filename) > 0: self.connect_db(filename) def connect_db(self, database=":memory:"): """ connect to an existing database at location filename """ self.list_manager.clear() # note: database can be either Database, or string, or QString if isinstance(database, Database): self.system.database = database else: self.system.database = self.system.create_database(db=database) # add minima to listWidged. do sorting after all minima are added for minimum in self.system.database.minima(): self.NewMinimum(minimum, sort_items=False) self.list_manager._sort_minima() self.NewTS(self.system.database.transition_states(order_energy=True)) self.list_manager.resize_columns_minima() self.list_manager.resize_columns_ts() self.system.database.on_minimum_added.connect(self.NewMinimum) self.system.database.on_minimum_removed(self.RemoveMinimum) self.system.database.on_ts_added.connect(self.NewTS) self.system.database.on_ts_removed.connect(self.RemoveTS) def SelectMinimum(self, minimum, set_selected=True): """when you click on a minimum in the basinhopping tab """ # print "selecting minimum", minimum._id, minimum.energy if set_selected: self.list_manager._select_main(minimum) return self.ui.ogl_main.setSystem(self.system) self.ui.ogl_main.setCoords(minimum.coords) self.ui.ogl_main.setMinimum(minimum) self.ui.oglTS.setSystem(self.system) if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=1, delete_all=True) def _SelectMinimum1(self, minimum, set_selected=True): """set the first minimum displayed in the connect tab""" if set_selected: self.list_manager._select1(minimum) return print "selecting minimum 1:", minimum._id, minimum.energy self.ui.oglPath.setSystem(self.system) self.ui.oglPath.setCoords(minimum.coords, index=1) # self.ui.oglPath.setMinimum(minimum, index=1) self.minima_selection.minimum1 = minimum self.minima_selection.coords1 = minimum.coords self.neb = None if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=1) self.on_minimum_1_selected(minimum) def _SelectMinimum2(self, minimum, set_selected=True): """set the second minimum displayed in the connect tab""" if set_selected: self.list_manager._select2(minimum) return print "selecting minimum 2:", minimum._id, minimum.energy self.ui.oglPath.setSystem(self.system) self.ui.oglPath.setCoords(minimum.coords, index=2) # self.ui.oglPath.setMinimum(minimum, index=2) self.minima_selection.minimum2 = minimum self.minima_selection.coords2 = minimum.coords self.neb = None if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=2) self.on_minimum_2_selected(minimum) def get_selected_minima(self): """return the two minima that have been chosen in the gui""" m1, m2 = self.minima_selection.minimum1, self.minima_selection.minimum2 if m1 is None or m2 is None: raise Exception("you must select two minima first") return m1, m2 def get_selected_coords(self): """return the two sets of coordinates that have been chosen in the gui note, that these may not be the same as what is stored in the minimum. E.g. they may be the aligned structures """ coords1, coords2 = self.minima_selection.coords1, self.minima_selection.coords2 if coords1 is None or coords2 is None: raise Exception("you must select two minima first") return coords1, coords2 def show_TS(self, ts): """ show the transition state and the associated minima in the 3d viewer """ self.ui.oglTS.setSystem(self.system) m1 = ts.minimum1 m2 = ts.minimum2 # put them in best alignment mindist = self.system.get_mindist() dist, m1coords, tscoords = mindist(m1.coords, ts.coords) dist, m2coords, tscoords = mindist(m2.coords, ts.coords) self.tscoordspath = np.array([m1coords, tscoords, m2coords]) labels = ["minimum: energy " + str(m1.energy) + " id " + str(m1._id)] labels += ["ts: energy " + str(ts.energy)] labels += ["minimum: energy " + str(m2.energy) + " id " + str(m2._id)] self.ui.oglTS.setCoordsPath(self.tscoordspath, frame=1, labels=labels) if self.usepymol: self.pymolviewer.update_coords(self.tscoordspath, index=1, delete_all=True) def on_btnAlign_clicked(self, clicked=None): """use mindist to align the minima. called when the align button is pressed """ if clicked is None: return coords1, coords2 = self.get_selected_coords() align = self.system.get_mindist() pot = self.system.get_potential() print "energy before alignment", pot.getEnergy(coords1), pot.getEnergy(coords2) dist, coords1, coords2 = align(coords1, coords2) print "energy after alignment", pot.getEnergy(coords1), pot.getEnergy(coords2) print "best alignment distance", dist self.ui.oglPath.setCoords(coords1, index=1) self.ui.oglPath.setCoords(coords2, index=2) self.minima_selection.coords1 = coords1 self.minima_selection.coords2 = coords2 if self.usepymol: self.pymolviewer.update_coords([coords1], index=1) self.pymolviewer.update_coords([coords2], index=2) def on_btnNEB_clicked(self, clicked=None): """do an NEB run (not a connect run). Don't find best alignment first""" if clicked is None: return coords1, coords2 = self.get_selected_coords() from neb_explorer import NEBExplorer if not hasattr(self, "nebexplorer"): self.nebexplorer = NEBExplorer(system=self.system, app=self.app, parent=self) self.nebexplorer.show() self.nebexplorer.new_neb(coords1, coords2, run=False) # def showFrame(self, i): # if hasattr(self, "nebcoords"): # self.ui.oglPath.setCoords(self.nebcoords[i,:]) def on_minimum_picked(self, min1): """called when a minimimum is clicked on in the graph or disconnectivity graph""" if (self.pick_count % 2) == 0: self._SelectMinimum1(min1) else: self._SelectMinimum2(min1) self.pick_count += 1 def on_btnDisconnectivity_graph_clicked(self, clicked=None): """show the disconnectivity graph it is interactive, so that when you click on an end point that minima is selected """ if clicked is None: return if not hasattr(self, "dgraph_dlg"): self.dgraph_dlg = DGraphDialog(self.system.database, parent=self) self.dgraph_dlg.dgraph_widget.minimum_selected.connect(self.on_minimum_picked) self.dgraph_dlg.dgraph_widget.minimum_selected.connect(self.SelectMinimum) self.dgraph_dlg.rebuild_disconnectivity_graph() self.dgraph_dlg.show() def on_btnShowGraph_clicked(self, clicked=None): """ show the graph of minima and transition states make it interactive, so that when you click on a point that minima is selected """ if clicked is None: return self.pick_count = 0 if not hasattr(self, "graphview"): self.graphview = GraphViewDialog(self.system.database, parent=self, app=self.app) self.graphview.widget.on_minima_picked.connect(self.on_minimum_picked) self.graphview.widget.on_minima_picked.connect(self.SelectMinimum) self.graphview.show() self.graphview.widget.make_graph() try: m1, m2 = self.get_selected_minima() self.graphview.widget._show_minimum_energy_path(m1, m2) except: self.graphview.widget.show_graph() def on_pushNormalmodesMin_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "normalmode_explorer"): self.normalmode_explorer = NormalmodeBrowser(self, self.system, self.app) min1 = self.ui.ogl_main.minima[1] if min1 is None: raise RuntimeError("you must select a minimum first") self.normalmode_explorer.set_coords(min1.coords) self.normalmode_explorer.show() def on_pushNormalmodesTS_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "normalmode_explorer"): self.normalmode_explorer = NormalmodeBrowser(self, self.system, self.app) ts = self.list_manager.get_selected_ts() if ts is None: raise RuntimeError("you must select a transition state first") self.normalmode_explorer.set_coords(ts.coords) self.normalmode_explorer.show() def NewMinimum(self, minimum, sort_items=True): """ add a new minimum to the system """ self.list_manager.NewMinimum(minimum, sort_items=sort_items) def RemoveMinimum(self, minimum): """remove a minimum from self.minima_list_model""" self.list_manager.RemoveMinimum(minimum) def NewTS(self, ts, sort=True): """add new transition state, or list of transition states""" self.list_manager.NewTS(ts, sort=sort) def RemoveTS(self, ts): """remove transition state""" raise Exception("removing transition states not implemented yet") obj = self.ui.list_TS tsid = id(ts) itms = self.ui.list_TS.findItems("*", QtCore.Qt.MatchWildcard) for i in itms: if i.tsid == tsid: obj.takeItem(obj.row(i)) def set_basinhopping_number_alive(self, nalive): """set the label that shows how many basinhopping processes are alive""" self.ui.label_bh_nproc.setText("%d B.H. processes" % nalive) def on_btn_start_basinhopping_clicked(self, clicked=None): """this is run when the start basinhopping button is clicked""" if clicked is None: return # set up the basinhopping manager if not already done if self.bhmanager is None: self.bhmanager = BHManager( self.system, self.system.database, on_number_alive_changed=self.set_basinhopping_number_alive ) # get the number of steps from the input box nstepsstr = self.ui.lineEdit_bh_nsteps.text() nsteps = None try: nsteps = int(nstepsstr) except ValueError: # ignore the text if it is the default text if "steps" not in nstepsstr: sys.stderr.write("can't convert %s to integer\n" % nstepsstr) # start a basinhopping run self.bhmanager.start_worker(nsteps=nsteps) def on_btn_stop_basinhopping_clicked(self, clicked=None): if clicked is None: return self.bhmanager.kill_all_workers() def on_action_delete_minimum_triggered(self, checked=None): if checked is None: return min1 = self.ui.ogl_main.minima[1] ret = QtGui.QMessageBox.question( self, "Deleting minima", "Do you want to delete minima %d with energy %g" % (min1._id, min1.energy), QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel, ) if ret == QtGui.QMessageBox.Ok: print "deleting minima" print "deleting minimum", min1._id, min1.energy self.RemoveMinimum(min1) self.system.database.removeMinimum(min1) def on_btnConnect_clicked(self, clicked=None): if clicked is None: return return self._doubleEndedConnect(reconnect=False) def on_btnReconnect_clicked(self, clicked=None): if clicked is None: return return self._doubleEndedConnect(reconnect=True) def _doubleEndedConnect(self, reconnect=False, min1min2=None): """ launch a double ended connect run to connect the two selected minima. If the minima are not connected, or reconnect is True, launch a connect browser in a separate window. Else just show the path in the OGL viewer """ # determine which minima to connect if min1min2 is None: min1, min2 = self.get_selected_minima() else: min1, min2 = min1min2 database = self.system.database if not reconnect: # check if the minima are already connected double_ended_connect = self.system.get_double_ended_connect( min1, min2, database, fresh_connect=False, verbosity=0 ) if double_ended_connect.graph.areConnected(min1, min2): print "minima are already connected. loading smoothed path in viewer" mints, S, energies = double_ended_connect.returnPath() clist = [m.coords for m in mints] smoothpath = self.system.smooth_path(clist) coords = np.array(smoothpath) self.nebcoords = coords self.nebenergies = np.array(energies) print "setting path in oglPath" self.ui.oglPath.setCoordsPath(coords) # , labels) # self.ui.oglPath.setCoords(coords[0,:], 1) # self.ui.oglPath.setCoords(None, 2) # self.ui.sliderFrame.setRange(0, coords.shape[0]-1) if self.usepymol: self.pymolviewer.update_coords(self.nebcoords, index=1, delete_all=True) return # make the connect viewer decviewer = ConnectViewer(self.system, self.system.database, min1, min2, parent=self, app=self.app) print "starting double ended" decviewer.show() decviewer.start() # store pointers self.double_ended_connect_runs.append(decviewer) def on_btn_connect_in_optim_clicked(self, clicked=None): """spawn an OPTIM job and retrieve the minima and transition states it finds""" if clicked is None: return min1, min2 = self.get_selected_minima() # existing_minima = set(self.system.database.minima()) spawner = self.system.get_optim_spawner(min1.coords, min2.coords) spawner.run() db = self.system.database newminima, newts = spawner.load_results(self.system.database) # for m in newminima: # if m not in existing_minima: # self.NewMinimum(m) # now use DoubleEndedConnect to test if they are connected graph = TSGraph(db) if graph.areConnected(min1, min2): # use double ended connect to draw the interpolated path # this is ugly self._doubleEndedConnect(reconnect=False, min1min2=(min1, min2)) def _merge_minima(self, min1, min2): mindist = self.system.get_mindist() dist, x1, x2 = mindist(min1.coords, min2.coords) query = "Do you want to merge minimum %d with energy %g" % (min1._id, min1.energy) query += " with minimum %d with energy %g" % (min2._id, min2.energy) query += " separated by distance %g" % (dist) ret = QtGui.QMessageBox.question(self, "Merging minima", query, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Ok: m1, m2 = min1, min2 if m1._id > m2._id: m1, m2 = m2, m1 print "merging minima", m1._id, m2._id # , ": minimum", m2._id, "will be deleted" self.system.database.mergeMinima(m1, m2) self.RemoveMinimum(m2) def on_action_merge_minima_triggered(self, checked=None): if checked is None: return min1, min2 = self.get_selected_minima() self._merge_minima(min1, min2) def on_action_compute_thermodynamic_info_triggered(self, checked=None): if checked is None: return def on_done(): print "done computing thermodynamic info" self._on_done = on_done # because on_finish stores a weak reference self.compute_thermodynamic_information(on_finish=self._on_done) # def launch_connect_explorer(self): # coords1, coords2 = self.get_selected_coords() # # if not hasattr(self, "local_connect_explorer"): # self.local_connect_explorer = ConnectExplorerDialog(self.system) # self.local_connect_explorer.nebwgt.process_events.connect(self.processEvents) # self.local_connect_explorer.show() # self.local_connect_explorer.createNEB(coords1, coords2) # self.local_connect_explorer.runNEB() def on_btn_close_all_clicked(self, checked=None): if checked is None: return print "closing all windows" for dv in self.double_ended_connect_runs: dv.hide() # del dv self.double_ended_connect_runs = [] try: self.local_connect_explorer.hide() del self.local_connect_explorer except AttributeError: pass try: self.dgraph_dlg.hide() del self.dgraph_dlg except AttributeError: pass try: self.nebexplorer.hide() del self.nebexplorer except AttributeError: pass try: self.rate_viewer.hide() del self.rate_viewer except AttributeError: pass def on_btn_connect_all_clicked(self, checked=None): if checked is None: return from pele.gui.connect_all import ConnectAllDialog # if hasattr(self, "connect_all"): # if not self.connect_all.isVisible(): # self.connect_all.show() # if not self.connect_all.is_running() self.connect_all = ConnectAllDialog(self.system, self.system.database, parent=self, app=self.app) self.connect_all.show() self.connect_all.start() def on_pushTakestepExplorer_clicked(self): if not hasattr(self, "takestep_explorer"): self.takestep_explorer = TakestepExplorer( parent=self, system=self.system, app=self.app, database=self.system.database ) self.takestep_explorer.show() def on_btn_heat_capacity_clicked(self, clicked=None): if clicked is None: return self.cv_viewer = HeatCapacityViewer(self.system, self.system.database, parent=self) self.cv_viewer.show() self.cv_viewer.rebuild_cv_plot() def compute_thermodynamic_information(self, on_finish=None): """compute thermodynamic information for minima and ts in the background call on_finish when the calculation is done """ # TODO: deal carefuly with what will happen if this is called again # before the first calculation is done. if self.thermo_worker is overwritten will # the first calculation stop? from pele.gui._cv_viewer import GetThermodynamicInfoParallelQT self.thermo_worker = GetThermodynamicInfoParallelQT(self.system, self.system.database, npar=1) if on_finish is not None: self.thermo_worker.on_finish.connect(on_finish) self.thermo_worker.start() njobs = self.thermo_worker.njobs print "calculating thermodynamics for", njobs, "minima and transition states" # def _compute_rates(self, min1, min2, T=1.): # """compute rates without first calculating thermodynamics # """ # print "computing rates at temperature T =", T # tslist = [ts for ts in self.system.database.transition_states() # if ts.fvib is not None] # rcalc = RateCalculation(tslist, [min1], [min2], T=T) # r12, r21 = rcalc.compute_rates() # print "rate from", min1._id, "to", min2._id, "=", r12 # print "rate from", min2._id, "to", min1._id, "=", r21 # # def compute_rates(self, min1, min2, T=1.): # """compute the transition rate from min1 to min2 and vice versa""" # def on_finish(): # print "thermodynamic calculation finished" # self._compute_rates(min1, min2) # self._on_finish_thermo_reference = on_finish # so it doeesn't get garbage collected # self.compute_thermodynamic_information(on_finish=on_finish) def on_btn_rates_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "rate_viewer"): m1, m2 = self.minima_selection.minimum1, self.minima_selection.minimum2 self.rate_viewer = RateViewer(self.system, self.system.database, parent=self) if m1 is not None: self.rate_viewer.update_A(m1) if m2 is not None: self.rate_viewer.update_B(m2) self.on_minimum_1_selected.connect(self.rate_viewer.update_A) self.on_minimum_2_selected.connect(self.rate_viewer.update_B) self.rate_viewer.show()
def __init__(self, value): self.__value = value self.changed = Signal()
def __init__(self, *args, **kwargs): super(GetThermodynamicInfoParallelQT, self).__init__(*args, **kwargs) self.on_finish = Signal()
def __init__(self, parent=None, nplots=3): MPLWidget.__init__(self, parent=parent) self.nplots = nplots self.on_neb_pick = Signal() self.mpl_connect('pick_event', self.on_pick)
class MainGUI(QtGui.QMainWindow): """ this is the main class for the pele gui Parameters ---------- app : the application object returned by QtGui.QApplication() systemtype : system class object the system class """ def __init__(self, app, systemtype, parent=None): QtGui.QWidget.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.systemtype = systemtype self.transition = None self.app = app self.double_ended_connect_runs = [] self.pick_count = 0 self.minima_selection = MySelection() self.on_minimum_1_selected = Signal() self.on_minimum_2_selected = Signal() # set up the list manager self.list_manager = ListViewManager(self) # define the system self.NewSystem() # finish setting up the list manager (this must be done after NewSystem() is called) self.list_manager.finish_setup() # try to load the pymol viewer. try: self.usepymol = self.system.params.gui.use_pymol except (KeyError, AttributeError): self.usepymol = config.getboolean("gui", "use_pymol") if self.usepymol: try: from .pymol_viewer import PymolViewer self.pymolviewer = PymolViewer(self.system.load_coords_pymol) except (ImportError or NotImplementedError): self.usepymol = False if not self.usepymol: # note: glutInit() must be called exactly once. pymol calls it # during pymol.finish_launching(), so if we call it again it will # give an error. On the other hand, if we're not using pymol we # must call it. from OpenGL.GLUT import glutInit glutInit() self.bhmanager = None def NewSystem(self): """ this is called to initialize the system with a database """ self.system = self.systemtype() self.connect_db() def on_action_edit_params_triggered(self, checked=None): if checked is None: return self.paramsdlg = DlgParams(self.system.params) self.paramsdlg.show() def processEvents(self): self.app.processEvents() def on_action_db_connect_triggered(self, checked=None): """ launch a file browser to connect to an existing database """ if checked is None: return filename = QtGui.QFileDialog.getSaveFileName(self, 'Select database', '.') if len(filename) > 0: self.connect_db(filename) def connect_db(self, database=":memory:"): """ connect to an existing database at location filename """ self.list_manager.clear() # note: database can be either Database, or string, or QString if isinstance(database, Database): self.system.database = database else: self.system.database = self.system.create_database(db=database) # add minima to listWidged. do sorting after all minima are added for minimum in self.system.database.minima(): self.NewMinimum(minimum, sort_items=False) self.list_manager._sort_minima() self.NewTS(self.system.database.transition_states(order_energy=True)) self.list_manager.resize_columns_minima() self.list_manager.resize_columns_ts() self.system.database.on_minimum_added.connect(self.NewMinimum) self.system.database.on_minimum_removed(self.RemoveMinimum) self.system.database.on_ts_added.connect(self.NewTS) self.system.database.on_ts_removed.connect(self.RemoveTS) def SelectMinimum(self, minimum, set_selected=True): """when you click on a minimum in the basinhopping tab """ # print "selecting minimum", minimum._id, minimum.energy if set_selected: self.list_manager._select_main(minimum) return self.ui.ogl_main.setSystem(self.system) self.ui.ogl_main.setCoords(minimum.coords) self.ui.ogl_main.setMinimum(minimum) self.ui.oglTS.setSystem(self.system) if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=1, delete_all=True) def _SelectMinimum1(self, minimum, set_selected=True): """set the first minimum displayed in the connect tab""" if set_selected: self.list_manager._select1(minimum) return print("selecting minimum 1:", minimum._id, minimum.energy) self.ui.oglPath.setSystem(self.system) self.ui.oglPath.setCoords(minimum.coords, index=1) # self.ui.oglPath.setMinimum(minimum, index=1) self.minima_selection.minimum1 = minimum self.minima_selection.coords1 = minimum.coords self.neb = None if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=1) self.on_minimum_1_selected(minimum) def _SelectMinimum2(self, minimum, set_selected=True): """set the second minimum displayed in the connect tab""" if set_selected: self.list_manager._select2(minimum) return print("selecting minimum 2:", minimum._id, minimum.energy) self.ui.oglPath.setSystem(self.system) self.ui.oglPath.setCoords(minimum.coords, index=2) # self.ui.oglPath.setMinimum(minimum, index=2) self.minima_selection.minimum2 = minimum self.minima_selection.coords2 = minimum.coords self.neb = None if self.usepymol: self.pymolviewer.update_coords([minimum.coords], index=2) self.on_minimum_2_selected(minimum) def get_selected_minima(self): """return the two minima that have been chosen in the gui""" m1, m2 = self.minima_selection.minimum1, self.minima_selection.minimum2 if m1 is None or m2 is None: raise Exception("you must select two minima first") return m1, m2 def get_selected_coords(self): """return the two sets of coordinates that have been chosen in the gui note, that these may not be the same as what is stored in the minimum. E.g. they may be the aligned structures """ coords1, coords2 = self.minima_selection.coords1, self.minima_selection.coords2 if coords1 is None or coords2 is None: raise Exception("you must select two minima first") return coords1, coords2 def show_TS(self, ts): """ show the transition state and the associated minima in the 3d viewer """ self.ui.oglTS.setSystem(self.system) m1 = ts.minimum1 m2 = ts.minimum2 # put them in best alignment mindist = self.system.get_mindist() dist, m1coords, tscoords = mindist(m1.coords, ts.coords) dist, m2coords, tscoords = mindist(m2.coords, ts.coords) self.tscoordspath = np.array([m1coords, tscoords, m2coords]) labels = ["minimum: energy " + str(m1.energy) + " id " + str(m1._id)] labels += ["ts: energy " + str(ts.energy)] labels += ["minimum: energy " + str(m2.energy) + " id " + str(m2._id)] self.ui.oglTS.setCoordsPath(self.tscoordspath, frame=1, labels=labels) if self.usepymol: self.pymolviewer.update_coords(self.tscoordspath, index=1, delete_all=True) def on_btnAlign_clicked(self, clicked=None): """use mindist to align the minima. called when the align button is pressed """ if clicked is None: return coords1, coords2 = self.get_selected_coords() align = self.system.get_mindist() pot = self.system.get_potential() print("energy before alignment", pot.getEnergy(coords1), pot.getEnergy(coords2)) dist, coords1, coords2 = align(coords1, coords2) print("energy after alignment", pot.getEnergy(coords1), pot.getEnergy(coords2)) print("best alignment distance", dist) self.ui.oglPath.setCoords(coords1, index=1) self.ui.oglPath.setCoords(coords2, index=2) self.minima_selection.coords1 = coords1 self.minima_selection.coords2 = coords2 if self.usepymol: self.pymolviewer.update_coords([coords1], index=1) self.pymolviewer.update_coords([coords2], index=2) def on_btnNEB_clicked(self, clicked=None): """do an NEB run (not a connect run). Don't find best alignment first""" if clicked is None: return coords1, coords2 = self.get_selected_coords() from .neb_explorer import NEBExplorer if not hasattr(self, "nebexplorer"): self.nebexplorer = NEBExplorer(system=self.system, app=self.app, parent=self) self.nebexplorer.show() self.nebexplorer.new_neb(coords1, coords2, run=False) # def showFrame(self, i): # if hasattr(self, "nebcoords"): # self.ui.oglPath.setCoords(self.nebcoords[i,:]) def on_minimum_picked(self, min1): """called when a minimimum is clicked on in the graph or disconnectivity graph""" if (self.pick_count % 2) == 0: self._SelectMinimum1(min1) else: self._SelectMinimum2(min1) self.pick_count += 1 def on_btnDisconnectivity_graph_clicked(self, clicked=None): """show the disconnectivity graph it is interactive, so that when you click on an end point that minima is selected """ if clicked is None: return if not hasattr(self, "dgraph_dlg"): self.dgraph_dlg = DGraphDialog(self.system.database, parent=self) self.dgraph_dlg.dgraph_widget.minimum_selected.connect( self.on_minimum_picked) self.dgraph_dlg.dgraph_widget.minimum_selected.connect( self.SelectMinimum) self.dgraph_dlg.rebuild_disconnectivity_graph() self.dgraph_dlg.show() def on_btnShowGraph_clicked(self, clicked=None): """ show the graph of minima and transition states make it interactive, so that when you click on a point that minima is selected """ if clicked is None: return self.pick_count = 0 if not hasattr(self, "graphview"): self.graphview = GraphViewDialog(self.system.database, parent=self, app=self.app) self.graphview.widget.on_minima_picked.connect( self.on_minimum_picked) self.graphview.widget.on_minima_picked.connect(self.SelectMinimum) self.graphview.show() self.graphview.widget.make_graph() try: m1, m2 = self.get_selected_minima() self.graphview.widget._show_minimum_energy_path(m1, m2) except Exception: self.graphview.widget.show_graph() def on_pushNormalmodesMin_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "normalmode_explorer"): self.normalmode_explorer = NormalmodeBrowser( self, self.system, self.app) min1 = self.ui.ogl_main.minima[1] if min1 is None: raise RuntimeError("you must select a minimum first") self.normalmode_explorer.set_coords(min1.coords) self.normalmode_explorer.show() def on_pushNormalmodesTS_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "normalmode_explorer"): self.normalmode_explorer = NormalmodeBrowser( self, self.system, self.app) ts = self.list_manager.get_selected_ts() if ts is None: raise RuntimeError("you must select a transition state first") self.normalmode_explorer.set_coords(ts.coords) self.normalmode_explorer.show() def NewMinimum(self, minimum, sort_items=True): """ add a new minimum to the system """ self.list_manager.NewMinimum(minimum, sort_items=sort_items) def RemoveMinimum(self, minimum): """remove a minimum from self.minima_list_model""" self.list_manager.RemoveMinimum(minimum) def NewTS(self, ts, sort=True): """add new transition state, or list of transition states""" self.list_manager.NewTS(ts, sort=sort) def RemoveTS(self, ts): """remove transition state""" raise Exception("removing transition states not implemented yet") obj = self.ui.list_TS tsid = id(ts) itms = self.ui.list_TS.findItems('*', QtCore.Qt.MatchWildcard) for i in itms: if i.tsid == tsid: obj.takeItem(obj.row(i)) def set_basinhopping_number_alive(self, nalive): """set the label that shows how many basinhopping processes are alive""" self.ui.label_bh_nproc.setText("%d B.H. processes" % nalive) def on_btn_start_basinhopping_clicked(self, clicked=None): """this is run when the start basinhopping button is clicked""" if clicked is None: return # set up the basinhopping manager if not already done if self.bhmanager is None: self.bhmanager = BHManager( self.system, self.system.database, on_number_alive_changed=self.set_basinhopping_number_alive) # get the number of steps from the input box nstepsstr = self.ui.lineEdit_bh_nsteps.text() nsteps = None try: nsteps = int(nstepsstr) except ValueError: # ignore the text if it is the default text if "steps" not in nstepsstr: sys.stderr.write("can't convert %s to integer\n" % nstepsstr) # start a basinhopping run self.bhmanager.start_worker(nsteps=nsteps) def on_btn_stop_basinhopping_clicked(self, clicked=None): if clicked is None: return self.bhmanager.kill_all_workers() def on_action_delete_minimum_triggered(self, checked=None): if checked is None: return min1 = self.ui.ogl_main.minima[1] ret = QtGui.QMessageBox.question( self, "Deleting minima", "Do you want to delete minima %d with energy %g" % (min1._id, min1.energy), QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Ok: print("deleting minima") print("deleting minimum", min1._id, min1.energy) self.RemoveMinimum(min1) self.system.database.removeMinimum(min1) def on_btnConnect_clicked(self, clicked=None): if clicked is None: return return self._doubleEndedConnect(reconnect=False) def on_btnReconnect_clicked(self, clicked=None): if clicked is None: return return self._doubleEndedConnect(reconnect=True) def _doubleEndedConnect(self, reconnect=False, min1min2=None): """ launch a double ended connect run to connect the two selected minima. If the minima are not connected, or reconnect is True, launch a connect browser in a separate window. Else just show the path in the OGL viewer """ # determine which minima to connect if min1min2 is None: min1, min2 = self.get_selected_minima() else: min1, min2 = min1min2 database = self.system.database if not reconnect: # check if the minima are already connected double_ended_connect = self.system.get_double_ended_connect( min1, min2, database, fresh_connect=False, verbosity=0) if double_ended_connect.graph.areConnected(min1, min2): print( "minima are already connected. loading smoothed path in viewer" ) mints, S, energies = double_ended_connect.returnPath() clist = [m.coords for m in mints] smoothpath = self.system.smooth_path(clist) coords = np.array(smoothpath) self.nebcoords = coords self.nebenergies = np.array(energies) print("setting path in oglPath") self.ui.oglPath.setCoordsPath(coords) # self.ui.oglPath.setCoords(coords[0,:], 1) # self.ui.oglPath.setCoords(None, 2) # self.ui.sliderFrame.setRange(0, coords.shape[0]-1) if self.usepymol: self.pymolviewer.update_coords(self.nebcoords, index=1, delete_all=True) return # make the connect viewer decviewer = ConnectViewer(self.system, self.system.database, min1, min2, parent=self, app=self.app) print("starting double ended") decviewer.show() decviewer.start() # store pointers self.double_ended_connect_runs.append(decviewer) def on_btn_connect_in_optim_clicked(self, clicked=None): """spawn an OPTIM job and retrieve the minima and transition states it finds""" if clicked is None: return min1, min2 = self.get_selected_minima() # existing_minima = set(self.system.database.minima()) spawner = self.system.get_optim_spawner(min1.coords, min2.coords) spawner.run() db = self.system.database newminima, newts = spawner.load_results(self.system.database) # for m in newminima: # if m not in existing_minima: # self.NewMinimum(m) # now use DoubleEndedConnect to test if they are connected graph = TSGraph(db) if graph.areConnected(min1, min2): # use double ended connect to draw the interpolated path # this is ugly self._doubleEndedConnect(reconnect=False, min1min2=(min1, min2)) def _merge_minima(self, min1, min2): mindist = self.system.get_mindist() dist, x1, x2 = mindist(min1.coords, min2.coords) query = "Do you want to merge minimum %d with energy %g" % ( min1._id, min1.energy) query += " with minimum %d with energy %g" % ( min2._id, min2.energy) query += " separated by distance %g" % dist ret = QtGui.QMessageBox.question(self, "Merging minima", query, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Ok: m1, m2 = min1, min2 if m1._id > m2._id: m1, m2 = m2, m1 print("merging minima", m1._id, m2._id) self.system.database.mergeMinima(m1, m2) self.RemoveMinimum(m2) def on_action_merge_minima_triggered(self, checked=None): if checked is None: return min1, min2 = self.get_selected_minima() self._merge_minima(min1, min2) def on_action_compute_thermodynamic_info_triggered(self, checked=None): if checked is None: return def on_done(): print("done computing thermodynamic info") self._on_done = on_done # because on_finish stores a weak reference self.compute_thermodynamic_information(on_finish=self._on_done) def on_btn_close_all_clicked(self, checked=None): if checked is None: return print("closing all windows") for dv in self.double_ended_connect_runs: dv.hide() # del dv self.double_ended_connect_runs = [] try: self.local_connect_explorer.hide() del self.local_connect_explorer except AttributeError: pass try: self.dgraph_dlg.hide() del self.dgraph_dlg except AttributeError: pass try: self.nebexplorer.hide() del self.nebexplorer except AttributeError: pass try: self.rate_viewer.hide() del self.rate_viewer except AttributeError: pass def on_btn_connect_all_clicked(self, checked=None): if checked is None: return from pele.gui.connect_all import ConnectAllDialog # if hasattr(self, "connect_all"): # if not self.connect_all.isVisible(): # self.connect_all.show() # if not self.connect_all.is_running() self.connect_all = ConnectAllDialog(self.system, self.system.database, parent=self, app=self.app) self.connect_all.show() self.connect_all.start() def on_pushTakestepExplorer_clicked(self): if not hasattr(self, "takestep_explorer"): self.takestep_explorer = TakestepExplorer( parent=self, system=self.system, app=self.app, database=self.system.database) self.takestep_explorer.show() def on_btn_heat_capacity_clicked(self, clicked=None): if clicked is None: return self.cv_viewer = HeatCapacityViewer(self.system, self.system.database, parent=self) self.cv_viewer.show() self.cv_viewer.rebuild_cv_plot() def compute_thermodynamic_information(self, on_finish=None): """compute thermodynamic information for minima and ts in the background call on_finish when the calculation is done """ # TODO: deal carefuly with what will happen if this is called again # before the first calculation is done. if self.thermo_worker is overwritten will # the first calculation stop? from pele.gui._cv_viewer import GetThermodynamicInfoParallelQT self.thermo_worker = GetThermodynamicInfoParallelQT( self.system, self.system.database, npar=1) if on_finish is not None: self.thermo_worker.on_finish.connect(on_finish) self.thermo_worker.start() njobs = self.thermo_worker.njobs print("calculating thermodynamics for", njobs, "minima and transition states") # def _compute_rates(self, min1, min2, T=1.): # """compute rates without first calculating thermodynamics # """ # print "computing rates at temperature T =", T # tslist = [ts for ts in self.system.database.transition_states() # if ts.fvib is not None] # rcalc = RateCalculation(tslist, [min1], [min2], T=T) # r12, r21 = rcalc.compute_rates() # print "rate from", min1._id, "to", min2._id, "=", r12 # print "rate from", min2._id, "to", min1._id, "=", r21 # # def compute_rates(self, min1, min2, T=1.): # """compute the transition rate from min1 to min2 and vice versa""" # def on_finish(): # print "thermodynamic calculation finished" # self._compute_rates(min1, min2) # self._on_finish_thermo_reference = on_finish # so it doeesn't get garbage collected # self.compute_thermodynamic_information(on_finish=on_finish) def on_btn_rates_clicked(self, clicked=None): if clicked is None: return if not hasattr(self, "rate_viewer"): m1, m2 = self.minima_selection.minimum1, self.minima_selection.minimum2 self.rate_viewer = RateViewer(self.system, self.system.database, parent=self) if m1 is not None: self.rate_viewer.update_A(m1) if m2 is not None: self.rate_viewer.update_B(m2) self.on_minimum_1_selected.connect(self.rate_viewer.update_A) self.on_minimum_2_selected.connect(self.rate_viewer.update_B) self.rate_viewer.show()