def _build_nodes(self): self._nodes = [] for plugin in pluginmanager.get_plugins_of_type( "GUIPlugin") + pluginmanager.get_plugins_of_type("EZPlugin"): node = Node(plugin, plugin.name) for name, stage in plugin.stages.items(): node.children.append( self._build_subnodes(name, stage, parent=node)) self._nodes.append(node)
def showMenu(self, pos): self.menu = QMenu() # Add all resource plugins self.actions = {} from xicam.plugins import manager as pluginmanager for plugin in pluginmanager.get_plugins_of_type("CatalogPlugin") + pluginmanager.get_plugins_of_type( "DataResourcePlugin"): self.actions[plugin.name] = QAction(plugin.name) self.actions[plugin.name].triggered.connect(partial(self._addBrowser, plugin)) self.menu.addAction(self.actions[plugin.name]) self.menu.popup(pos)
def detect_mimetypes(filename: str) -> List[str]: """ Take in a filename; return a mimetype string like 'image/tiff'. """ # First rely on custom "sniffers" that can employ file signatures (magic # numbers) or any other format-specific tricks to extract a mimetype. matched_mimetypes = list() with open(filename, "rb") as file: # The choice of 64 bytes is arbitrary. We may increase this in the # future if we discover reason to. Therefore, sniffers should not # assume that they will receive this exact number of bytes. first_bytes = file.read(64) from xicam.plugins import manager as plugin_manager for sniffer in plugin_manager.get_plugins_of_type("sniffers"): matched_mimetype = sniffer(filename, first_bytes) if matched_mimetype: matched_mimetypes.append(matched_mimetype) # Guessing the mimetype from the mimemtype db is quick, lets do it always matched_mimetype = mimetypes.guess_type(filename)[0] if matched_mimetype: matched_mimetypes.append(matched_mimetype) if not matched_mimetypes: raise UnknownFileType( f"Could not identify the MIME type of {filename}") return matched_mimetypes
def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = MenuDict() operations = pluginmanager.get_plugins_of_type("OperationPlugin") if self.operation_filter is not None: operations = filter(self.operation_filter, operations) for operation in operations: categories = operation.categories if not categories: categories = [("Uncategorized", ) ] # put found operations into a default category for categories_tuple in categories: if isinstance(categories_tuple, str): categories_tuple = (categories_tuple, ) submenu = sortingDict categories_list = list(categories_tuple) while categories_list: category = categories_list.pop(0) submenu = submenu[category] submenu['___'].append(operation) self._mkMenu(sortingDict)
def __init__(self): # # Enforce global style within the console # with open('xicam/gui/style.stylesheet', 'r') as f: # style = f.read() # style = (qdarkstyle.load_stylesheet() + style) # Setup the kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() kernel = self.kernel_manager.kernel kernel.gui = 'qt' # Push Xi-cam variables into the kernel kernel.shell.push({ plugin.name: plugin for plugin in pluginmanager.get_plugins_of_type("GUIPlugin") + pluginmanager.get_plugins_of_type("EZPlugin") }) # Observe plugin changes pluginmanager.attach(self.pluginsChanged) # Continue kernel setuppluginmanager.getPluginsOfCategory("GUIPlugin") self.kernel_client = self.kernel_manager.client() threads.invoke_in_main_thread(self.kernel_client.start_channels) # Setup console widget def stop(): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() control = RichJupyterWidget() control.kernel_manager = self.kernel_manager threads.invoke_in_main_thread(setattr, control, "kernel_client", self.kernel_client) control.exit_requested.connect(stop) # control.style_sheet = style control.syntax_style = u'monokai' control.set_default_style(colors='Linux') # Setup layout self.stages = {'Terminal': GUILayout(control)} # Save for later self.kernel = kernel super(IPythonPlugin, self).__init__()
def __init__(self): super(AstropyQSpectraFit, self).__init__() self.model.limits = { plugin.name: plugin for plugin in pluginmanager.get_plugins_of_type( 'Fittable1DModelPlugin') } self.model.value = list(self.model.limits.values())[0]
def __init__(self): super(DeviceDialog, self).__init__() # Set size and position # self.setGeometry(0, 0, 800, 500) frameGm = self.frameGeometry() screen = QApplication.desktop().screenNumber( QApplication.desktop().cursor().pos()) centerPoint = QApplication.desktop().screenGeometry(screen).center() frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) self.namedynamically = True # Setup fields self.name = QLineEdit() self.devicestring = QLineEdit() self.controller = QComboBox() self.deviceclass = QComboBox() for name in self.deviceclasses: self.deviceclass.addItem(name) # TODO: add controller plugin # Temporary hard coded values for plugin in pluginmanager.get_plugins_of_type('ControllerPlugin'): self.controller.addItem(plugin.name()) # Setup dialog buttons self.addButton = QPushButton("&Add") self.connectButton = QPushButton("Test C&onnect") self.cancelButton = QPushButton("&Cancel") self.addButton.clicked.connect(self.add) self.connectButton.clicked.connect(self.connect) self.cancelButton.clicked.connect(self.close) self.buttonboxWidget = QDialogButtonBox() self.buttonboxWidget.addButton(self.addButton, QDialogButtonBox.AcceptRole) self.buttonboxWidget.addButton(self.connectButton, QDialogButtonBox.AcceptRole) self.buttonboxWidget.addButton(self.cancelButton, QDialogButtonBox.RejectRole) # Wireup signals self.devicestring.textChanged.connect(self.fillName) self.name.textChanged.connect(self.stopDynamicName) # Compose main layout mainLayout = QFormLayout() mainLayout.addRow('Device Name', self.name) mainLayout.addRow('Device PV', self.devicestring) mainLayout.addRow('Controller Type', self.controller) mainLayout.addRow('Device Class', self.deviceclass) mainLayout.addRow(self.buttonboxWidget) self.setLayout(mainLayout) self.setWindowTitle("Add Device...") # Set modality self.setModal(True)
def createIcons(self): self.contentsModel.clear() for plugin in pluginmanager.get_plugins_of_type("SettingsPlugin"): item = QStandardItem(plugin.icon, plugin.name()) item.widget = plugin.widget item.setTextAlignment(Qt.AlignHCenter) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item.setSizeHint(QSize(136, 80)) self.contentsModel.appendRow(item)
def applicable_ingestors(filename, mimetype): """ Take in a filename and its mimetype; return a list of compatible ingestors. """ # Find ingestor(s) for this mimetype. ingestors = [] from xicam.plugins import manager as plugin_manager for ingestor in plugin_manager.get_plugins_of_type("ingestors"): if ingestor._name == mimetype: ingestors.append(ingestor) return ingestors
def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = {} for plugin in pluginmanager.get_plugins_of_type("OperationPlugin"): typeOfOperationPlugin = plugin.getCategory() if not typeOfOperationPlugin in sortingDict.keys(): sortingDict[typeOfOperationPlugin] = [] sortingDict[typeOfOperationPlugin].append(plugin) for key in sortingDict.keys(): self.functionmenu.addSeparator() self.functionmenu.addAction(key) self.functionmenu.addSeparator() for plugin in sortingDict[key]: self.functionmenu.addAction( plugin.name, partial(self.addOperation, plugin, autoconnectall=True))
def as_parameter(self): return [{ "name": "Model", "type": "list", "limits": self.limits.get( 'model', { plugin.name: plugin for plugin in pluginmanager.get_plugins_of_type( 'Fittable1DModelPlugin') }) }, { "name": "Model Parameters", "type": "group" }]
def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = {} for plugin in pluginmanager.get_plugins_of_type("OperationPlugin"): typeOfOperationPlugin = plugin.categories # TODO : should OperationPlugin be responsible for initializing categories # to some placeholder value (instead of [])? if typeOfOperationPlugin == []: typeOfOperationPlugin = "uncategorized" # put found operations into a default category if not typeOfOperationPlugin in sortingDict.keys(): sortingDict[typeOfOperationPlugin] = [] sortingDict[typeOfOperationPlugin].append(plugin) for key in sortingDict.keys(): self.functionmenu.addSeparator() self.functionmenu.addAction(key) self.functionmenu.addSeparator() for plugin in sortingDict[key]: self.functionmenu.addAction( plugin.name, partial(self.addOperation, plugin, autoconnectall=True))
def restore(self): for plugin in pluginmanager.get_plugins_of_type("SettingsPlugin"): plugin.restore() self.apply()
def pluginsChanged(self): self.kernel.shell.push({ plugin.name: plugin for plugin in pluginmanager.get_plugins_of_type("GUIPlugin") + pluginmanager.get_plugins_of_type("EZPlugin") })
def apply(self): for plugin in pluginmanager.get_plugins_of_type("SettingsPlugin"): plugin.save()
def request_reload(): for plugin in pluginmanager.get_plugins_of_type("SettingsPlugin"): plugin.restore() plugin.save()
def load_header(uris: List[Union[str, Path]] = None, uuid: str = None): """ Load a document object, either from a file source or a databroker source, by uuid. If loading from a filename, the file will be registered in databroker. Parameters ---------- uris uuid Returns ------- NonDBHeader """ from xicam.plugins import manager as pluginmanager # must be a late import # ext = Path(filename).suffix[1:] # for cls, extensions in extension_map.items(): # if ext in extensions: # First try to see if we have a databroker ingestor, then fall-back to Xi-cam DataHandlers ingestor = None filename = str(Path(uris[0])) # Sanity checks if Path(filename).is_dir(): msg.logMessage("Opening dir; nothing to load.") return if not Path(filename).exists(): raise FileExistsError( f"Attempted to load non-existent file: {filename}") try: mimetypes = detect_mimetypes(filename) except UnknownFileType as ex: msg.logError(ex) mimetypes = [] else: msg.logMessage(f"Mimetypes detected: {mimetypes}") # TODO: here, we try each valid mimetype; some GUI for selection will be needed for mimetype in mimetypes: try: ingestor = choose_ingestor(filename, mimetype) except NoIngestor as e: pass else: msg.logMessage(f"Ingestor selected: {ingestor}") break if ingestor: document = list(ingestor(uris)) uid = document[0][1]["uid"] catalog = BlueskyInMemoryCatalog() # TODO -- change upsert signature to put start and stop as kwargs # TODO -- ask about more convenient way to get a BlueskyRun from a document generator catalog.upsert(document[0][1], document[-1][1], ingestor, [uris], {}) return catalog[uid] else: warn(f"No applicable ingestor found. Falling-back to DataHandlers") handlercandidates = [] ext = Path(uris[0]).suffix for plugin in pluginmanager.get_plugins_of_type("DataHandlerPlugin"): if ext in plugin.DEFAULT_EXTENTIONS: handlercandidates.append(plugin) if not handlercandidates: return NonDBHeader({}, [], [], {}) # try: msg.logMessage(f"Handler selected: {handlercandidates[0]}") return NonDBHeader(**handlercandidates[0].ingest(uris))