def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical('Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project)
def insert_application(self, application): application['created_time'] = datetime.now() applier = dict(username=g.user['username'], name=g.user['name']) application['applier'] = applier application['status'] = 0 pm = ProjectManager() apply_project = pm.find_project_by_id(application['project']['id']) self.conn.projects.update_one( {'_id': ObjectId(application['project']['id'])}, { '$push': { 'appliers': applier } } ) application['project']['name'] = apply_project['name'] result = self.conn.application.insert_one(application) message = dict() message['created_time'] = datetime.now() message['receiver'] = apply_project['creator']['id'] message['sender'] = applier message['type'] = 0 message['status'] = 0 message['attachment'] = dict(application=str(result.inserted_id)) self.conn.messages.insert_one(message) return True
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical('Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project)
def main(ctx): if not is_internet_up(): print("Please check your intenet connection") return config = configparser.ConfigParser() config.read('config.ini') ctx.obj["github"] = Github(config["GITHUB"]["API"]) ctx.obj["todo_manager"] = TodoManager(config["TODOIST"]["API"]) ctx.obj["path"] = config["PATH"] ctx.obj["project_manager"] = ProjectManager()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical( 'Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project) def load_plugins(self): """This just gets all the plugins (no reference to pipeline)""" plugins = collections.OrderedDict() filenames = [ f for f in sorted(os.listdir('plugins')) if f.endswith('.py') ] for filename in filenames: name, ext = os.path.splitext(filename) p = self.load_plugin('plugins.' + name, None) if p: plugins[name] = p return plugins def load_plugin(self, module, plugin_position): try: m = importlib.import_module(module) if not hasattr(m, 'MyPlugin'): return None p = m.MyPlugin(self.project, plugin_position) # p.run() except: print('Failed to import \'{}\'.'.format(module)) raise else: return p # def reset_pipeline_plugins(self, plugin_names): # for i, plugin_name in enumerate(plugin_names): # p = self.load_plugin('plugins.' + plugin_name, i) # if p: # self.plugins[plugin_name] = p # if self.current_plugin: # self.set_plugin(self.current_plugin, None) def reload_pipeline_plugins(self): for i, plugin_name in enumerate( self.pipeline_model.get_plugin_names()): p = self.load_plugin('plugins.' + plugin_name, i) if p: self.plugins[plugin_name] = p # def set_x(val): # self.sidebar.x_origin.setValue(val) # def set_y(val): # self.sidebar.y_origin.setValue(val) # if plugin_name == 'set_coordinate_system': # p.widget.x_origin_changed[float].connect(self.set_x) # p.widget.y_origin_changed[float].connect(set_y) if self.current_plugin: self.set_plugin(self.current_plugin, None) def setup_ui(self): self.pipeconf = PipeconfDialog(self.plugins, self) self.datadialog = DataDialog(self) self.pl_frame = QFrame() splitter = QSplitter(self) self.enable = lambda yes: splitter.setEnabled(yes) splitter.setHandleWidth(3) splitter.setStyleSheet('QSplitter::handle {background: #cccccc;}') splitter.addWidget(self.sidebar) splitter.addWidget(self.pl_frame) # splitter.setStretchFactor(0, 0) # splitter.setStretchFactor(1, 1) self.setCentralWidget(splitter) self.menu = self.menuBar() m = self.menu.addMenu('&File') a = QAction('&New project', self) a.setShortcut('Ctrl+N') a.setStatusTip('Create new project') a.triggered.connect(self.create_project) m.addAction(a) a = QAction('&Open project', self) a.setShortcut('Ctrl+O') a.setStatusTip('Open project') a.triggered.connect(self.open_project) m.addAction(a) a = QAction("&Quit", self) a.setShortcut("Ctrl+Q") a.setStatusTip('Leave The App') a.setIcon(QIcon('pics/quit.png')) a.triggered.connect(self.close) m.addAction(a) about_action = QAction('&About ' + APPNAME, self) about_action.setStatusTip('About ' + APPNAME) about_action.triggered.connect(self.about) about_action.setShortcut('F1') whats_this_action = QWhatsThis.createAction( QAction('&What\'s This?', self)) whats_this_action.setShortcut('Shift+F1') m = self.menu.addMenu('&Project') m.setEnabled(False) a = QAction("&Close", self) a.setStatusTip('Close project') a.triggered.connect(self.close_project) m.addAction(a) a = QAction("&Reset All Plugin Parameters", self) a.setStatusTip( 'This is useful if you experience JSON-related issues allowing for a clean slate' ) a.triggered.connect(self.reset_all_params) m.addAction(a) self.project_menu = m help_menu = self.menu.addMenu('&Help') help_menu.addAction(about_action) help_menu.addAction(whats_this_action) def reset_all_params(self): for plugin_position, p in enumerate(self.project.pipeline): if p['name'] in self.plugins.keys(): plugin = self.plugins[p['name']] if hasattr(plugin, 'widget'): if hasattr(plugin.widget, 'setup_params'): if not hasattr(plugin.widget, 'params'): plugin.widget.params = self.project.pipeline[ plugin_position] plugin.widget.project = self.project plugin.widget.plugin_position = plugin_position try: plugin.widget.setup_params(reset=True) except: print("Failed to reset " + p['name']) def setup_signals(self): self.datadialog.reload_plugins.connect(self.reload_pipeline_plugins) self.sidebar.open_pipeconf_requested.connect(self.open_pipeconf) self.sidebar.open_datadialog_requested.connect(self.open_datadialog) self.sidebar.automate_pipeline_requested.connect( self.automate_pipeline) self.sidebar.x_origin_changed[float].connect( functools.partial(self.set_project_coordinate_system, 'x')) self.sidebar.y_origin_changed[float].connect( functools.partial(self.set_project_coordinate_system, 'y')) self.sidebar.units_per_pixel_changed[float].connect( functools.partial(self.set_project_coordinate_system, 'units_per_pixel')) self.plugins['set_coordinate_system'].widget.x_origin_changed[ float].connect( functools.partial(self.set_project_coordinate_system, 'x')) self.plugins['set_coordinate_system'].widget.y_origin_changed[ float].connect( functools.partial(self.set_project_coordinate_system, 'y')) # todo: add signals from set_coordinate_system here self.sidebar.pl_list.active_plugin_changed[str, int].connect( self.set_plugin) self.sidebar.pl_list.setModel(self.pipeconf.pipeline_list.model()) def set_project_coordinate_system(self, key, value): #todo: add update for view self.project['origin'] = list(self.project['origin']) if key == 'x': self.project['origin'][0] = value self.project.save() elif key == 'y': self.project['origin'][1] = value self.project.save() elif key == 'units_per_pixel': self.project['unit_per_pixel'] = value self.project.save() if self.current_plugin in self.plugins.keys(): self.plugins[self.current_plugin].widget.view.update() def create_project(self): project = self.project_manager.new_project() if project: self.load_project(project) def load_project(self, project): self.clean() self.project = project self.setWindowTitle(APPNAME + ' - ' + project.name) self.enable(True) self.project_menu.setEnabled(True) QSettings().setValue('path_of_last_project', project.path) pipeline = [] for plugin_dict in self.project.pipeline: # include fix to update old versions to new format try: plugin_name = plugin_dict['name'] except: attrs = json.load(open('../templates/mbeproject.json')) pipeline_template = attrs['pipeline'] # pipeline_names = [p['name'] for p in pipeline_template] # plugins = self.load_plugins() # for plugin_name in pipeline_names: # for plugin in plugins: # if plugin == plugin_name: # pipeline.append((plugin, plugins[plugin].name)) # break QMessageBox.about( self, 'Critical Error in pipeline. Manual Reset Recommended', """ <p>Please quit and replace the pipeline in your project JSON file with</p> <p></p> <td>%s</td> <p>which can be copied from <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer/blob/master/templates/mbeproject.json">here</a></p> <p>Only the pipeline section needs to be replaced</p> """ % pipeline_template) # qtutil.critical("Pipeline appears to be corrupt. " # "Please replace your current pipeline in the JSON file with \n" # " " + str(pipeline_template) + "which can be copied from \n" + # < a href = "https://github.com/Frikster/Mesoscale-Brain-Explorer/issues" > here < / a > < / p > # "https://github.com/Frikster/Mesoscale-Brain-Explorer/blob/master/templates/mbeproject.json") return for plugin in self.plugins: if plugin == plugin_name: pipeline.append((plugin, self.plugins[plugin].name)) break self.pipeline_model.set_plugins(pipeline) self.reload_pipeline_plugins() self.sidebar.setup_sidebar_values(project) # self.reset_pipeline_plugins([p[0] for p in pipeline]) def open_project(self, path=''): project = self.project_manager.open_project(path) if project: self.load_project(project) def close_project(self): self.clean() self.project = None self.setWindowTitle(APPNAME) self.project_menu.setEnabled(False) self.enable(False) def set_plugin(self, plugin_name, plugin_position): p = self.load_plugin('plugins.' + str(plugin_name), plugin_position) if not p: return self.current_plugin = plugin_name self.plugins[plugin_name] = p def set_x(val): self.sidebar.x_origin.setValue(val) def set_y(val): self.sidebar.y_origin.setValue(val) if plugin_name == 'set_coordinate_system': p.widget.x_origin_changed[float].connect(set_x) p.widget.y_origin_changed[float].connect(set_y) lt = QVBoxLayout() lt.addWidget(p.widget) self.clean_plugin() self.pl_frame.setLayout(lt) # p.run() def clean_plugin(self): if self.pl_frame.layout(): clear_layout(self.pl_frame.layout()) QWidget().setLayout(self.pl_frame.layout()) def clean(self): model = self.sidebar.pl_list.model() if model: model.clear() self.clean_plugin() def open_pipeconf(self): self.pipeconf.exec_() pipeline = self.pipeline_model.get_plugin_names() self.project.set_pipeline(pipeline) self.project.save() def open_datadialog(self): self.datadialog.update(self.project) self.datadialog.exec_() def automate_pipeline(self): # order by index ordered_q_model_indexes = sorted( self.sidebar.pl_list.selectedIndexes(), key=lambda x: x.row(), reverse=False) if not ordered_q_model_indexes: qtutil.info( "Select all the plugins you want to process through. Use shift or ctrl to select multiple" ) import_plugin_indexes = [ ind for ind in range(len(ordered_q_model_indexes)) if self.plugins[ordered_q_model_indexes[ind].data( Qt.UserRole)].name in constants.IMPORT_PLUGINS ] if not import_plugin_indexes: p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected( ) # find the number of files outputted by the first plugin for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() if not p.check_ready_for_automation(number_of_outputs): qtutil.critical(p.automation_error_message()) return number_of_outputs = p.output_number_expected( number_of_outputs) # find the number of outputs p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] input_paths = p.get_input_paths() if not input_paths: qtutil.critical( "The first plugin in the pipeline does not have a set of input files selected" ) return for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths ordered_q_model_indexes_segments = [] for i, import_ind in enumerate(import_plugin_indexes): if i < len(import_plugin_indexes) - 1: # ordered_q_model_indexes are the indices in the GUI. # retrieve the indices from where this import plugin is (import_ind) to # the index right before the next import plugin ordered_q_model_indexes_segment = ordered_q_model_indexes[ import_ind:(import_plugin_indexes[i + 1])] else: ordered_q_model_indexes_segment = ordered_q_model_indexes[ import_ind:] ordered_q_model_indexes_segments = ordered_q_model_indexes_segments + [ ordered_q_model_indexes_segment ] import_paths = [] for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): import_plugin = self.plugins[ ordered_q_model_indexes_segment[0].data(Qt.UserRole)] qtutil.info( "Please select all your files for the pipeline starting from import plugin " + str(i)) input_paths = import_plugin.get_input_paths() import_paths = import_paths + [input_paths] if not input_paths: qtutil.critical( "import plugin " + str(i) + " in the pipeline does not have a set of input files selected" ) return # ensure all selected plugins are ready for automation for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): not_import_plugins = [ self.plugins[ordered_q_model_indexes_segment[j].data( Qt.UserRole)] for j in range(1, len(ordered_q_model_indexes_segment)) ] number_of_outputs = len(import_paths[i]) for not_import_plugin in not_import_plugins: if not not_import_plugin.check_ready_for_automation( number_of_outputs): qtutil.critical( not_import_plugin.automation_error_message()) return number_of_outputs = not_import_plugin.output_number_expected( number_of_outputs) for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): input_paths = import_paths[i] for q_model_index in ordered_q_model_indexes_segment: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths # p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] # input_paths = p.get_input_paths() # if not input_paths: # qtutil.critical("The first plugin in the pipeline does not have a set of input files selected") # return # # for q_model_index in ordered_q_model_indexes: # p = self.plugins[q_model_index.data(Qt.UserRole)] # output_paths = p.run(input_paths) # input_paths = output_paths # self.sidebar.pl_list.selectedIndexes()[0].data(Qt.UserRole) # # self.sidebar.pl_list.selectedIndexes()[0].row() # self.sidebar.pl_list.model().data(self.sidebar.pl_list.selectedIndexes()[0]) def about(self): author = 'Cornelis Dirk Haupt' date = '2017' QMessageBox.about( self, 'About ' + APPNAME, """ <b>%s</b> <p>An online readme, including user manual and developer tutorial can be found <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer">here</a></p> <p>Use the "what's this" feature to click on any UI component and learn how to use it</p> <p>Please submit any feature requests or issues <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer/issues">here</a></p> <p></p> <p><table border="0" width="150"> <tr> <td>Author:</td> <td>%s</td> </tr> <tr> <td>Version:</td> <td>%s</td> </tr> <tr> <td>Date:</td> <td>%s</td> </tr> </table></p> """ % (APPNAME, author, VERSION, date))
kshift = (1,1,1), # grid centered at supercell L point pseudos = ['Ge.pbe-kjpaw.UPF'], # PBE pseudopotential system = T_system # the interstitial system ) # link together the simulation cascade # current relax gets structure from previous if len(relaxations)>0: # if it exists relax.depends(relaxations[-1],'structure') #end if relaxations.append(relax) # add relax simulation to the list #end for # perform the simulations pm = ProjectManager() # start the project manager pm.add_simulations(relaxations) # give it the relax calculations pm.run_project() # run all the jobs # analyze the results performed_runs = not settings.generate_only and not settings.status_only if performed_runs: print print 'Relaxation results:' print '-------------------' print ' kgrid starting force max force # of cycles' for ik in range(len(supercell_kgrids)):
conv_thr=1e-6, # convergence threshold kgrid=kgrid, # supercell k-point grid kshift=(1, 1, 1), # grid centered at supercell L point pseudos=['Ge.pbe-kjpaw.UPF'], # PBE pseudopotential system=T_system # the interstitial system ) # link together the simulation cascade # current relax gets structure from previous if len(relaxations) > 0: # if it exists relax.depends(relaxations[-1], 'structure') #end if relaxations.append(relax) # add relax simulation to the list #end for # perform the simulations pm = ProjectManager() # start the project manager pm.add_simulations(relaxations) # give it the relax calculations pm.run_project() # run all the jobs # analyze the results performed_runs = not settings.generate_only and not settings.status_only if performed_runs: print print 'Relaxation results:' print '-------------------' print ' kgrid starting force max force # of cycles' for ik in range(len(supercell_kgrids)): kgrid = supercell_kgrids[ik] relax = relaxations[ik]
from fastapi import Depends, FastAPI, HTTPException, BackgroundTasks from starlette.responses import Response from starlette.staticfiles import StaticFiles from fastapi.security import HTTPBasic, HTTPBasicCredentials from starlette.status import HTTP_401_UNAUTHORIZED from io import BytesIO, open import os import json from storage import Storage from project import ProjectManager from models import Project storage = Storage() project_manager = ProjectManager() app = FastAPI() # project @app.get("/api/projects") def list_projects(): return storage.list_buckets() @app.get("/api/projects/{bucket_name}") def project_details(bucket_name): try: data = storage.get_object(bucket_name, 'project.json') return json.loads(data) except: files = []
substeps=3, # MC steps taken w/o computing E_local samplesperthread=40 # No. of dmc walkers per thread ), dmc( # dmc parameters timestep=0.01, # dmc timestep (1/Ha) warmupsteps=50, # No. of MC steps before data is collected blocks=400, # No. of data blocks recorded in scalar.dat steps=5, # No. of steps per block nonlocalmoves=True # use Casula's T-moves ), # (retains variational principle for NLPP's) ], # return a list or object containing simulations return_list=False) #the project manager monitors all runs pm = ProjectManager() # give it the simulation objects pm.add_simulations(qsims.list()) # run all the simulations pm.run_project() # print out the total energy performed_runs = not settings.generate_only and not settings.status_only if performed_runs: # get the qmcpack analyzer object # it contains all of the statistically analyzed data from the run qa = qsims.qmc.load_analyzer_image() # get the local energy from dmc.dat le = qa.dmc[1].dmc.LocalEnergy # dmc series 1, dmc.dat, local energy
timestep = 0.01, # dmc timestep (1/Ha) warmupsteps = 50, # No. of MC steps before data is collected blocks = 400, # No. of data blocks recorded in scalar.dat steps = 5, # No. of steps per block nonlocalmoves = True # use Casula's T-moves ), # (retains variational principle for NLPP's) ], # return a list or object containing simulations return_list = False ) #the project manager monitors all runs pm = ProjectManager() # give it the simulation objects pm.add_simulations(qsims.list()) # run all the simulations pm.run_project() # print out the total energy performed_runs = not settings.generate_only and not settings.status_only if performed_runs: # get the qmcpack analyzer object # it contains all of the statistically analyzed data from the run qa = qsims.qmc.load_analyzer_image()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical('Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project) def load_plugins(self): """This just gets all the plugins (no reference to pipeline)""" plugins = collections.OrderedDict() filenames = [f for f in sorted(os.listdir('plugins')) if f.endswith('.py')] for filename in filenames: name, ext = os.path.splitext(filename) p = self.load_plugin('plugins.' + name, None) if p: plugins[name] = p return plugins def load_plugin(self, module, plugin_position): try: m = importlib.import_module(module) if not hasattr(m, 'MyPlugin'): return None p = m.MyPlugin(self.project, plugin_position) # p.run() except: print('Failed to import \'{}\'.'.format(module)) raise else: return p # def reset_pipeline_plugins(self, plugin_names): # for i, plugin_name in enumerate(plugin_names): # p = self.load_plugin('plugins.' + plugin_name, i) # if p: # self.plugins[plugin_name] = p # if self.current_plugin: # self.set_plugin(self.current_plugin, None) def reload_pipeline_plugins(self): for i, plugin_name in enumerate(self.pipeline_model.get_plugin_names()): p = self.load_plugin('plugins.' + plugin_name, i) if p: self.plugins[plugin_name] = p # def set_x(val): # self.sidebar.x_origin.setValue(val) # def set_y(val): # self.sidebar.y_origin.setValue(val) # if plugin_name == 'set_coordinate_system': # p.widget.x_origin_changed[float].connect(self.set_x) # p.widget.y_origin_changed[float].connect(set_y) if self.current_plugin: self.set_plugin(self.current_plugin, None) def setup_ui(self): self.pipeconf = PipeconfDialog(self.plugins, self) self.datadialog = DataDialog(self) self.pl_frame = QFrame() splitter = QSplitter(self) self.enable = lambda yes: splitter.setEnabled(yes) splitter.setHandleWidth(3) splitter.setStyleSheet('QSplitter::handle {background: #cccccc;}') splitter.addWidget(self.sidebar) splitter.addWidget(self.pl_frame) # splitter.setStretchFactor(0, 0) # splitter.setStretchFactor(1, 1) self.setCentralWidget(splitter) self.menu = self.menuBar() m = self.menu.addMenu('&File') a = QAction('&New project', self) a.setShortcut('Ctrl+N') a.setStatusTip('Create new project') a.triggered.connect(self.create_project) m.addAction(a) a = QAction('&Open project', self) a.setShortcut('Ctrl+O') a.setStatusTip('Open project') a.triggered.connect(self.open_project) m.addAction(a) a = QAction("&Quit", self) a.setShortcut("Ctrl+Q") a.setStatusTip('Leave The App') a.setIcon(QIcon('pics/quit.png')) a.triggered.connect(self.close) m.addAction(a) about_action = QAction('&About ' + APPNAME, self) about_action.setStatusTip('About ' + APPNAME) about_action.triggered.connect(self.about) about_action.setShortcut('F1') whats_this_action = QWhatsThis.createAction(QAction('&What\'s This?', self)) whats_this_action.setShortcut('Shift+F1') m = self.menu.addMenu('&Project') m.setEnabled(False) a = QAction("&Close", self) a.setStatusTip('Close project') a.triggered.connect(self.close_project) m.addAction(a) a = QAction("&Reset All Plugin Parameters", self) a.setStatusTip('This is useful if you experience JSON-related issues allowing for a clean slate') a.triggered.connect(self.reset_all_params) m.addAction(a) self.project_menu = m help_menu = self.menu.addMenu('&Help') help_menu.addAction(about_action) help_menu.addAction(whats_this_action) def reset_all_params(self): for plugin_position, p in enumerate(self.project.pipeline): if p['name'] in self.plugins.keys(): plugin = self.plugins[p['name']] if hasattr(plugin, 'widget'): if hasattr(plugin.widget, 'setup_params'): if not hasattr(plugin.widget, 'params'): plugin.widget.params = self.project.pipeline[plugin_position] plugin.widget.project = self.project plugin.widget.plugin_position = plugin_position try: plugin.widget.setup_params(reset=True) except: print("Failed to reset " + p['name']) def setup_signals(self): self.datadialog.reload_plugins.connect(self.reload_pipeline_plugins) self.sidebar.open_pipeconf_requested.connect(self.open_pipeconf) self.sidebar.open_datadialog_requested.connect(self.open_datadialog) self.sidebar.automate_pipeline_requested.connect(self.automate_pipeline) self.sidebar.x_origin_changed[float].connect(functools.partial(self.set_project_coordinate_system, 'x')) self.sidebar.y_origin_changed[float].connect(functools.partial(self.set_project_coordinate_system, 'y')) self.sidebar.units_per_pixel_changed[float].connect(functools.partial(self.set_project_coordinate_system, 'units_per_pixel')) self.plugins['set_coordinate_system'].widget.x_origin_changed[float].connect(functools.partial( self.set_project_coordinate_system, 'x')) self.plugins['set_coordinate_system'].widget.y_origin_changed[float].connect(functools.partial( self.set_project_coordinate_system, 'y')) # todo: add signals from set_coordinate_system here self.sidebar.pl_list.active_plugin_changed[str, int].connect(self.set_plugin) self.sidebar.pl_list.setModel(self.pipeconf.pipeline_list.model()) def set_project_coordinate_system(self, key, value): #todo: add update for view self.project['origin'] = list(self.project['origin']) if key == 'x': self.project['origin'][0] = value self.project.save() elif key == 'y': self.project['origin'][1] = value self.project.save() elif key == 'units_per_pixel': self.project['unit_per_pixel'] = value self.project.save() if self.current_plugin in self.plugins.keys(): self.plugins[self.current_plugin].widget.view.update() def create_project(self): project = self.project_manager.new_project() if project: self.load_project(project) def load_project(self, project): self.clean() self.project = project self.setWindowTitle(APPNAME + ' - ' + project.name) self.enable(True) self.project_menu.setEnabled(True) QSettings().setValue('path_of_last_project', project.path) pipeline = [] for plugin_dict in self.project.pipeline: # include fix to update old versions to new format try: plugin_name = plugin_dict['name'] except: attrs = json.load(open('../templates/mbeproject.json')) pipeline_template = attrs['pipeline'] # pipeline_names = [p['name'] for p in pipeline_template] # plugins = self.load_plugins() # for plugin_name in pipeline_names: # for plugin in plugins: # if plugin == plugin_name: # pipeline.append((plugin, plugins[plugin].name)) # break QMessageBox.about(self, 'Critical Error in pipeline. Manual Reset Recommended', """ <p>Please quit and replace the pipeline in your project JSON file with</p> <p></p> <td>%s</td> <p>which can be copied from <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer/blob/master/templates/mbeproject.json">here</a></p> <p>Only the pipeline section needs to be replaced</p> """ % pipeline_template) # qtutil.critical("Pipeline appears to be corrupt. " # "Please replace your current pipeline in the JSON file with \n" # " " + str(pipeline_template) + "which can be copied from \n" + # < a href = "https://github.com/Frikster/Mesoscale-Brain-Explorer/issues" > here < / a > < / p > # "https://github.com/Frikster/Mesoscale-Brain-Explorer/blob/master/templates/mbeproject.json") return for plugin in self.plugins: if plugin == plugin_name: pipeline.append((plugin, self.plugins[plugin].name)) break self.pipeline_model.set_plugins(pipeline) self.reload_pipeline_plugins() self.sidebar.setup_sidebar_values(project) # self.reset_pipeline_plugins([p[0] for p in pipeline]) def open_project(self, path=''): project = self.project_manager.open_project(path) if project: self.load_project(project) def close_project(self): self.clean() self.project = None self.setWindowTitle(APPNAME) self.project_menu.setEnabled(False) self.enable(False) def set_plugin(self, plugin_name, plugin_position): p = self.load_plugin('plugins.' + str(plugin_name), plugin_position) if not p: return self.current_plugin = plugin_name self.plugins[plugin_name] = p def set_x(val): self.sidebar.x_origin.setValue(val) def set_y(val): self.sidebar.y_origin.setValue(val) if plugin_name == 'set_coordinate_system': p.widget.x_origin_changed[float].connect(set_x) p.widget.y_origin_changed[float].connect(set_y) lt = QVBoxLayout() lt.addWidget(p.widget) self.clean_plugin() self.pl_frame.setLayout(lt) # p.run() def clean_plugin(self): if self.pl_frame.layout(): clear_layout(self.pl_frame.layout()) QWidget().setLayout(self.pl_frame.layout()) def clean(self): model = self.sidebar.pl_list.model() if model: model.clear() self.clean_plugin() def open_pipeconf(self): self.pipeconf.exec_() pipeline = self.pipeline_model.get_plugin_names() self.project.set_pipeline(pipeline) self.project.save() def open_datadialog(self): self.datadialog.update(self.project) self.datadialog.exec_() def automate_pipeline(self): # order by index ordered_q_model_indexes = sorted(self.sidebar.pl_list.selectedIndexes(), key=lambda x: x.row(), reverse=False) if not ordered_q_model_indexes: qtutil.info("Select all the plugins you want to process through. Use shift or ctrl to select multiple") import_plugin_indexes = [ind for ind in range(len(ordered_q_model_indexes)) if self.plugins[ordered_q_model_indexes[ind].data(Qt.UserRole)].name in constants.IMPORT_PLUGINS] if not import_plugin_indexes: p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() # find the number of files outputted by the first plugin for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() if not p.check_ready_for_automation(number_of_outputs): qtutil.critical(p.automation_error_message()) return number_of_outputs = p.output_number_expected(number_of_outputs) # find the number of outputs p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] input_paths = p.get_input_paths() if not input_paths: qtutil.critical("The first plugin in the pipeline does not have a set of input files selected") return for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths ordered_q_model_indexes_segments = [] for i, import_ind in enumerate(import_plugin_indexes): if i < len(import_plugin_indexes)-1: # ordered_q_model_indexes are the indices in the GUI. # retrieve the indices from where this import plugin is (import_ind) to # the index right before the next import plugin ordered_q_model_indexes_segment = ordered_q_model_indexes[import_ind:(import_plugin_indexes[i+1])] else: ordered_q_model_indexes_segment = ordered_q_model_indexes[import_ind:] ordered_q_model_indexes_segments = ordered_q_model_indexes_segments + [ordered_q_model_indexes_segment] import_paths = [] for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): import_plugin = self.plugins[ordered_q_model_indexes_segment[0].data(Qt.UserRole)] qtutil.info("Please select all your files for the pipeline starting from import plugin " + str(i)) input_paths = import_plugin.get_input_paths() import_paths = import_paths + [input_paths] if not input_paths: qtutil.critical("import plugin " + str(i) + " in the pipeline does not have a set of input files selected") return # ensure all selected plugins are ready for automation for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): not_import_plugins = [self.plugins[ordered_q_model_indexes_segment[j].data(Qt.UserRole)] for j in range(1, len(ordered_q_model_indexes_segment))] number_of_outputs = len(import_paths[i]) for not_import_plugin in not_import_plugins: if not not_import_plugin.check_ready_for_automation(number_of_outputs): qtutil.critical(not_import_plugin.automation_error_message()) return number_of_outputs = not_import_plugin.output_number_expected(number_of_outputs) for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): input_paths = import_paths[i] for q_model_index in ordered_q_model_indexes_segment: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths # p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] # input_paths = p.get_input_paths() # if not input_paths: # qtutil.critical("The first plugin in the pipeline does not have a set of input files selected") # return # # for q_model_index in ordered_q_model_indexes: # p = self.plugins[q_model_index.data(Qt.UserRole)] # output_paths = p.run(input_paths) # input_paths = output_paths # self.sidebar.pl_list.selectedIndexes()[0].data(Qt.UserRole) # # self.sidebar.pl_list.selectedIndexes()[0].row() # self.sidebar.pl_list.model().data(self.sidebar.pl_list.selectedIndexes()[0]) def about(self): author = 'Cornelis Dirk Haupt' date = '2017' QMessageBox.about(self, 'About ' + APPNAME, """ <b>%s</b> <p>An online readme, including user manual and developer tutorial can be found <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer">here</a></p> <p>Use the "what's this" feature to click on any UI component and learn how to use it</p> <p>Please submit any feature requests or issues <a href="https://github.com/Frikster/Mesoscale-Brain-Explorer/issues">here</a></p> <p></p> <p><table border="0" width="150"> <tr> <td>Author:</td> <td>%s</td> </tr> <tr> <td>Version:</td> <td>%s</td> </tr> <tr> <td>Date:</td> <td>%s</td> </tr> </table></p> """ % (APPNAME, author, VERSION, date))