def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' #initialise the widgets self.tree = self.mask_interface.getTreeView() self.mask_combo_box = self.mask_interface.getComboBox() self.add_mask_button = QtWidgets.QPushButton("+") self.remove_mask_button = QtWidgets.QPushButton("-") self.mask_tree_layout.addWidget(self.tree) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.mask_combo_box.setSizePolicy(size_policy) self.combo_layout.addWidget(self.mask_combo_box) self.combo_layout.addWidget(self.add_mask_button) self.combo_layout.addWidget(self.remove_mask_button) #initialise the graphs self.my_canvas = MultiCanvasItem(self.mask_widget_visual, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self.ax.axes.general_handler['Aspect ratio'] = [True, 1.] self.ax.pointer.pointer_handler['Sticky'] = 2 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.ax.draw()
def setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' ############################################## #add the file drop self.data_list_files = DropListView(self.data_group_dialog, 'tof_file_drop') sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.data_list_files.sizePolicy().hasHeightForWidth()) self.data_list_files.setSizePolicy(sizePolicy) self.data_list_files.setMinimumSize(QtCore.QSize(0, 30)) self.data_list_files.setVerticalScrollMode( QtWidgets.QAbstractItemView.ScrollPerItem) self.data_list_files.setObjectName("data_list_files") self.add_custome_file.addWidget(self.data_list_files) ############################################## #add the file drop self.data_list_loaded.setStyleSheet( "QListWidget::item { border: 2px solid black ;background-color: palette(Midlight) }" "QListWidget::item:selected { background-color: palette(Mid) }") self.data_list_loaded.setSizeAdjustPolicy( QtWidgets.QListWidget.AdjustToContents) self.data_list_meta.setStyleSheet( "QListWidget::item { border: 2px solid black ;background-color: palette(Midlight) }" "QListWidget::item:selected { background-color: palette(Mid) }") ############################################## #add the self.my_canvas = MultiCanvasItem(self.data_widget_graph, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self._prev_plot = self.ax.addPlot('Surface', Name='Surface') self.ax.axes.general_handler['Active'] = [False] * 4 self.ax.pointer.pointer_handler['Sticky'] = 2 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.ax.draw()
def setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' self.setupUi(self.window) self.my_canvas = MultiCanvasItem(self.graph_widget, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) ax = self.my_canvas.getSubplot(0, 0) ax.pointer.pointer_handler['Sticky'] = 2
def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area. ''' self.setupUi(self.local_widget) self.process_tree = ResultTree(self.data_group) self.verticalLayout_4.addWidget(self.process_tree) self.horizontalLayout = QtWidgets.QHBoxLayout() self.process_refresh_button = QtWidgets.QPushButton( 'Refresh', self.data_group) self.process_refresh_button.setObjectName("process_refresh_button") self.horizontalLayout.addWidget(self.process_refresh_button) self.verticalLayout_4.addLayout(self.horizontalLayout) self.process_list_plot = PlotTree(self.plot_items_group) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.process_list_plot.sizePolicy().hasHeightForWidth()) self.verticalLayout_2.addWidget(self.process_list_plot) self.my_canvas = MultiCanvasItem(self.process_widget_plot, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self.ax.pointer.pointer_handler['Sticky'] = 3 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.result_handler_ui = ResultHandlerUI(self, self.process_tree, self.process_list_plot)
class DisplayRawWindowLayout(Ui_raw_display): ''' This class will manage the raw import machinery. the UI is inherited through Ui_main_window from the Qt designer anf then converted through pyuic5 ''' def __init__(self, window, window_manager): ############################################## #Local pointers Ui_raw_display.__init__(self) self.window_manager = window_manager self.window = window self.setup() def setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' self.setupUi(self.window) self.my_canvas = MultiCanvasItem(self.graph_widget, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) ax = self.my_canvas.getSubplot(0, 0) ax.pointer.pointer_handler['Sticky'] = 2 def link(self, import_object, mode='3D'): ''' This routine will link to the io manager class from the core. ''' self._mode = mode self.import_object = import_object self.initialize() self.connect() def initialize(self): ''' This routine will link to the io manager class from the core. ''' self.echo_drop.addItems( [str(e) for e in self.import_object.meta_handler.values['Echo']]) self.foil_spin.setMinimum(0) self.foil_spin.setMaximum( self.import_object.data_handler.dimension[0] - 1) self.time_spin.setMinimum(0) self.time_spin.setMaximum( self.import_object.data_handler.dimension[1] - 1) if self._mode == '3D': self.time_spin.show() self.time_check.show() self.ax = self.my_canvas.getSubplot(0, 0) self.plot = self.ax.addPlot('Surface', Name='Surface') histogram = self.plot.childFromName('Surface').childFromName( 'Shader').getHistogramItem() self.ax.addHistogramItem('right', histogram) elif self._mode == '4D': self.time_spin.hide() self.time_check.hide() self.my_canvas.canvas_nodes[0][0][0].handler['Type'] = '3D' self.ax = self.my_canvas.getSubplot(0, 0) self.plot = self.ax.addPlot('Volume', Name='Volume') histogram = self.plot.childFromName('Volume').childFromName( 'Shader').getHistogramItem() self.ax.addHistogramItem('right', histogram) self.ax.draw() self.draw() self.connect() def connect(self): ''' This routine will link to the io manager class from the core. ''' self.foil_spin.valueChanged.connect(self.draw) self.time_spin.valueChanged.connect(self.draw) self.echo_drop.currentIndexChanged.connect(self.draw) self.foil_check.stateChanged.connect(self.draw) self.time_check.stateChanged.connect(self.draw) self.log_check.stateChanged.connect(self.draw) self.norm_check.stateChanged.connect(self.draw) def draw(self, stuff=None): ''' ''' data = self.import_object.file_handler.getElement( self.echo_drop.currentIndex()) if self.foil_check.isChecked(): data = np.sum(data, axis=0) else: data = data[self.foil_spin.value()] if self._mode == '4D': data = data elif self.time_check.isChecked(): data = np.sum(data, axis=0) else: data = data[self.time_spin.value()] if self.log_check.isChecked(): data = np.log10(data + 1) if self.norm_check.isChecked(): data_min = np.amin(data) data_max = np.amax(data) data = (data - data_min) / (data_max - data_min) * 10. if self._mode == '3D': self.plot.setData(x=np.array([i for i in range(data.shape[0])]), y=np.array([i for i in range(data.shape[1])]), z=data) elif self._mode == '4D': self.plot.setData( x=np.array([i for i in range(data.shape[0])], dtype=np.float) / 5, y=np.array([j for j in range(data.shape[1])], dtype=np.float) / 10., z=np.array([k for k in range(data.shape[2])], dtype=np.float) / 10, data=np.array(data, dtype=np.float64))
class PageDataWidget(Ui_data_import): def __init__(self, stack, parent): Ui_data_import.__init__(self) self.parent = parent self.stack = stack self.local_widget = QtWidgets.QWidget() self.setupUi(self.local_widget) self.setup() self.connect() self.initialize() def initialize(self): ''' Reset all the inputs and all the fields present in the current view. ''' self.elements = [] self.meta_elements = [] self.io_core = None if not self.data_list_files.model() is None: self.data_list_files.model().clear() self.data_list_loaded.clear() self.data_list_meta.clear() def setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' ############################################## #add the file drop self.data_list_files = DropListView(self.data_group_dialog, 'tof_file_drop') sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.data_list_files.sizePolicy().hasHeightForWidth()) self.data_list_files.setSizePolicy(sizePolicy) self.data_list_files.setMinimumSize(QtCore.QSize(0, 30)) self.data_list_files.setVerticalScrollMode( QtWidgets.QAbstractItemView.ScrollPerItem) self.data_list_files.setObjectName("data_list_files") self.add_custome_file.addWidget(self.data_list_files) ############################################## #add the file drop self.data_list_loaded.setStyleSheet( "QListWidget::item { border: 2px solid black ;background-color: palette(Midlight) }" "QListWidget::item:selected { background-color: palette(Mid) }") self.data_list_loaded.setSizeAdjustPolicy( QtWidgets.QListWidget.AdjustToContents) self.data_list_meta.setStyleSheet( "QListWidget::item { border: 2px solid black ;background-color: palette(Midlight) }" "QListWidget::item:selected { background-color: palette(Mid) }") ############################################## #add the self.my_canvas = MultiCanvasItem(self.data_widget_graph, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self._prev_plot = self.ax.addPlot('Surface', Name='Surface') self.ax.axes.general_handler['Active'] = [False] * 4 self.ax.pointer.pointer_handler['Sticky'] = 2 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.ax.draw() def link(self, io_core): ''' This routine will link to the io manager class from the core. ''' self.initialize() self.io_core = io_core self.populateAll() def unlink(self): ''' To remove the item ''' self.io_core = None def connect(self): ''' This routine will link to the io manager class from the core. ''' #connect buttons self.data_button_meta_add.clicked.connect(self.openMetadataWindow) self.data_button_meta_remove.clicked.connect(self.removeMeta) self.data_button_meta_all.clicked.connect(self.propagateMeta) self.data_button_files_add.clicked.connect(self.getFiles) self.data_button_files_reset.clicked.connect(self.resetFiles) self.data_button_populate.clicked.connect(self.populate) self.data_button_validate.clicked.connect(self.generateDataset) self.data_button_files_remove.clicked.connect(self.removeFile) self.data_button_prev.clicked.connect(self.hide_preview) self.data_button_add_object.clicked.connect(self.addElement) self.data_button_remove_object.clicked.connect(self.removeElement) #connect lists self.data_list_files.drop_success.connect(self.addFiles) self.data_list_loaded.clicked.connect(self.setCurrentElement) self.data_list_loaded.itemSelectionChanged.connect( self.setCurrentElementSilent) #the dimension fields self.data_input_foils.textChanged.connect(self.dimChanged) self.data_input_time_channel.textChanged.connect(self.dimChanged) self.data_input_pix_x.textChanged.connect(self.dimChanged) self.data_input_pix_y.textChanged.connect(self.dimChanged) def openMetadataWindow(self): ''' This routine will launch the metadat window. ''' if len(self.elements) == 0: dialog(parent=self.local_widget, icon='error', title='No data element set', message='No data element initialized. Add one first...', add_message= 'You can add a dataset by going to File>add element.') else: self.parent.window_manager.newWindow('MetaWindow') self.parent.window_manager.active_windows[ 'MetaWindow'].target.link(self.meta_handler) def hide_preview(self): ''' This routine will launch the metadat window. ''' self.data_widget_graph.setVisible( not self.data_widget_graph.isVisible()) if self.data_widget_graph.isVisible(): self.data_button_prev.setText('Hide') else: self.data_button_prev.setText('Show') def openVisualWindow(self): ''' This routine will launch the metadat window. ''' self.parent.window_manager.newWindow('RawVisual') self.parent.window_manager.active_windows['RawVisual'].target.link( self.import_object) def openVisualWindow4D(self): ''' This routine will launch the metadat window. ''' self.parent.window_manager.newWindow('RawVisual') self.parent.window_manager.active_windows['RawVisual'].target.link( self.import_object, mode='4D') def removeMeta(self): ''' This routine will remove an element of the selected meta. ''' index = self.data_list_meta.currentRow() self.meta_handler.removeElement(index) self.setMetaList() def propagateMeta(self): ''' This routine will simply propagate the current meta information to all other meta windows. ''' for element in self.io_core.import_objects: element.meta_handler = copy.deepcopy(self.meta_handler) def _setCurrentObject(self, index): ''' ''' self.import_object = self.io_core.import_objects[index] self.file_handler = self.io_core.import_objects[index].file_handler self.meta_handler = self.io_core.import_objects[index].meta_handler self.data_handler = self.io_core.import_objects[index].data_handler self.current_element = self.elements[index] self.setFileList() self.setMetaList() self.setDimInputs() def setCurrentElement(self, row=None): ''' On clicking an element the system will set the classes linked to the current element ''' if isinstance(row, int): index = row else: index = self.data_list_loaded.currentRow() if not self.io_core == None: self._setCurrentObject(index) self.elements[index].widget.setFocus() def setCurrentElementSilent(self, row=None): ''' On clicking an element the system will set the classes linked to the current element ''' if isinstance(row, int): index = row else: index = self.data_list_loaded.currentRow() if not self.io_core == None: self._setCurrentObject(index) def addElement(self): ''' Add an element into the list which is loaded from a custom widget. ''' self.io_core.addObject() self.elements.append( LoadedDataWidget(self.io_core.import_objects[-1].data_handler, parent=self.data_list_loaded)) self.elements[-1].vis_button.clicked.connect(self.openVisualWindow) self.elements[-1].vis_button_2.clicked.connect(self.openVisualWindow4D) self.setCurrentElement(len(self.io_core.import_objects) - 1) def addElementSilent(self, i): ''' Add an element into the list which is loaded from a custom widget. ''' self.elements.append( LoadedDataWidget(self.io_core.import_objects[i].data_handler, parent=self.data_list_loaded)) self.elements[-1].vis_button.clicked.connect(self.openVisualWindow) self.elements[-1].vis_button_2.clicked.connect(self.openVisualWindow4D) self.setCurrentElement(i) def removeElement(self): ''' Remove an element from the current dataset ''' row = self.data_list_loaded.currentRow() self.data_list_loaded.takeItem(row) del self.elements[row] del self.io_core.import_objects[row] def clear(self): ''' Clear the current element list ''' self.data_list_loaded.clear() self.elements = [] def setMetaList(self): ''' grabs the information from the initial meta container in the core and then produces the adequate list. ''' self.clearMeta() for i in range(len(self.meta_handler.selected_meta)): self.addMetaElement() self.meta_elements[-1].setParentList( self.meta_handler.selected_meta[i]) self.meta_elements[-1].edited.connect(self.meta_handler.editValue) def addMetaElement(self): ''' ''' self.meta_elements.append(MetaWidget(self.data_list_meta)) def clearMeta(self): ''' ''' self.data_list_meta.clear() self.meta_elements = [] def getFiles(self): ''' ''' if len(self.elements) == 0: dialog(parent=self.local_widget, icon='error', title='No data element set', message='No data element initialized. Add one first...', add_message= 'You can add a dataset by going to File>add element.') else: filter = "All (*);; TOF (*.tof);;PAD (*.pad)" file_name = QtWidgets.QFileDialog() file_name.setFileMode(QtWidgets.QFileDialog.ExistingFiles) names = file_name.getOpenFileNames(self.parent.window, 'Select files ...', '', filter) self.addFiles(names[0]) def addFiles(self, filenames): ''' Adding files to the data either through the filedialog or the drag and drop. ''' self.file_handler.addFiles(filenames) self.setFileList() def setFileList(self): ''' This will be the loading of files to the io file handler class. ''' self.file_model = QtGui.QStandardItemModel() for element in self.file_handler.nice_path_files: item = QtGui.QStandardItem(element) self.file_model.appendRow(item) self.data_list_files.setModel(self.file_model) self.data_list_files.selectionModel().selectionChanged.connect( self.setPrev) def removeFile(self): ''' This will reset the file view and the associated core io routine. ''' self.file_handler.removeFile(self.data_list_files.currentIndex().row()) self.setFileList() def resetFiles(self): ''' This will reset the file view and the associated core io routine. ''' self.file_handler.initialize() self.setFileList() def setPrev(self, item_selection): ''' This will generate the preview of the dataset selected in the current file view. ''' if not len(self.file_handler.total_path_files) == 0: self.file_handler.genPrev(item_selection.indexes()[0].row()) self.displayPrev() def displayPrev(self): ''' This routine will display the preview of the selected dataset processed by setPrev. ''' self._prev_plot.setData( x=np.array([ i for i in range(self.file_handler.current_preview.shape[0]) ]), y=np.array([ i for i in range(self.file_handler.current_preview.shape[1]) ]), z=self.file_handler.current_preview) def populate(self, warning=True): ''' This routine will call the generator for the currently active object. ''' self.import_object.processObject() self.current_element.setMeta(self.meta_handler.values, self.file_handler.nice_path_files) self.current_element.initialize() try: self.import_object.meta_handler.values['Echo'] except: if warning: dialog( parent=self.local_widget, icon='error', title='Echo time not processed', message= 'The echo time has not been processed. This is probably due to a lack of deinitions. See details...', add_message= 'The calculation of the echo time require the presence of the Wavelength, the first and second frequency attributed the the first and second RF coils and finally the lsd distance in between them extracted from the metadata. One or multiple of them are missing. Please rectify.' ) def populateAll(self): ''' This routine will call the generator for the currently active object. ''' self.parent.setActivity("Populating data", 0, len(self.io_core.import_objects)) for i in range(len(self.io_core.import_objects)): self.parent.setProgress("Adding element " + str(i + 1), i + 1) self.addElementSilent(i) self.parent.setProgress("Populating element " + str(i + 1), i + 1) self.populate(warning=False) self.parent.fadeActivity() def generateDataset(self): ''' This routine will call the generator for the currently active object. ''' sanity = self.io_core.generate() print(sanity) if sanity[0] is None: self.parent.widgetClasses[0].refreshData() self.parent.widgetClasses[3].link(self.parent.handler.current_env) elif sanity[0] == 'Echo issue': dialog( parent=self.local_widget, icon='error', title='Data echo time point has no reference. ', message= 'Some echo time values could not be found in the reference:\n' + str(sanity[1][0]), add_message= 'The reference measurment is important to process the contrast value. There should be one measuremnt for every echo time of the dataset. You can specify which measurement should be the reference by checking the reference checkbox within the widget.' ) elif sanity[0] == 'No reference': dialog( parent=self.local_widget, icon='error', title='No reference set', message= 'You did not specify which one of the measurements should be set as reference. See details...', add_message= 'The reference measurment is important to process the contrast value. There should be one measuremnt for every echo time of the dataset. You can specify which measurement should be the reference by checking the reference checkbox within the widget.' ) def save(self): ''' This will launch the save file of the io class ''' filters = "mieze_save.py" file_path = QtWidgets.QFileDialog.getSaveFileName( self.parent.window, 'Select file', filters)[0] self.io_core.saveToPython(file_path) def load(self): ''' This will launch the save file of the io class ''' filters = "*.py" file_path = QtWidgets.QFileDialog.getOpenFileName( self.parent.window, 'Select file', filters)[0] if not file_path == '': self.clear() output = self.io_core.loadFromPython(file_path, self) self.testLoadOutput(output, file_path) def testLoadOutput(self, output, file_path): ''' Test the output with the user and notify him if anything went wrong ''' try: passed = all([ all([subelement[0] for subelement in element]) for element in output ]) if not passed: meta_string = [] folder_string = [] for element in output: if not element[0][0]: meta_string.append('Invalid meta file location: ' + element[0][1]) if not element[1][0]: folder_string.append('Invalid file folder location: ' + element[1][1]) dialog( parent=self.local_widget, icon='warning', title='Could not load all files', message= 'Some files and folders seem to either have moved or not exist. Please rebase them manually in the import file located at:\n' + file_path, det_message='\n\n'.join(meta_string + folder_string)) except: pass def dimChanged(self): ''' This will launch the save file of the io class ''' dim = [ int(self.data_input_foils.text()), int(self.data_input_time_channel.text()), int(self.data_input_pix_x.text()), int(self.data_input_pix_y.text()) ] self.data_handler.dimension = list(dim) def setDimInputs(self): ''' This routine will simply propagate the current meta information to all other meta windows. ''' self.data_input_foils.setText(str(self.data_handler.dimension[0])) self.data_input_time_channel.setText( str(self.data_handler.dimension[1])) self.data_input_pix_x.setText(str(self.data_handler.dimension[2])) self.data_input_pix_y.setText(str(self.data_handler.dimension[3]))
def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' #initialise the widgets self._live = False self.tree = self.mask_interface.getTreeView() self.mask_combo_box = self.mask_interface.getComboBox() self.add_mask_button = QtWidgets.QPushButton("+") self.remove_mask_button = QtWidgets.QPushButton("-") self.mask_tree_layout.addWidget(self.tree) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.mask_combo_box.setSizePolicy(size_policy) self.combo_layout.addWidget(self.mask_combo_box) self.combo_layout.addWidget(self.add_mask_button) self.combo_layout.addWidget(self.remove_mask_button) #initialise the graphs self.my_canvas = MultiCanvasItem(self.mask_widget_visual, grid=[[True, True], [True, True]], x_ratios=[1, 1], y_ratios=[1, 1], background="w", highlightthickness=0) #set the subplots as local self.ax = self.my_canvas.getSubplot(0, 0) self.ax.axes.label_handler['Active'] = [True, True, True, True] self.ax.axes.label_handler['Text'] = ['py', 'px', 'None', 'None'] self.bx = self.my_canvas.getSubplot(0, 1) self.bx.axes.label_handler['Active'] = [True, True, True, True] self.bx.axes.label_handler['Text'] = ['py', 'px', 'None', 'None'] self.cx = self.my_canvas.getSubplot(1, 0) self.cx.axes.label_handler['Active'] = [True, True, True, True] self.cx.axes.label_handler['Text'] = [ 'Intensity', 'Time channel', 'None', 'None' ] self.dx = self.my_canvas.getSubplot(1, 1) self.dx.axes.label_handler['Active'] = [True, True, True, True] self.dx.axes.label_handler['Text'] = [ 'Contrast', 'Echo Time', 'None', 'None' ] self.dx.axes.general_handler['Log'] = [True, False] self.dx.zoomer['Zoom fixed'] = [False, True] self.dx.zoomer['Zoom fixed range'] = [0, 1, 0, 1] #set the two bin self.first_surface_plot = self.ax.addPlot('Surface', Name='Data area') self.second_surface_plot = self.bx.addPlot('Surface', Name='Mask and Data area') histogram_0 = self.first_surface_plot.childFromName( 'Surface').childFromName('Shader').getHistogramItem() self.ax.addHistogramItem('right', histogram_0) histogram_1 = self.second_surface_plot.childFromName( 'Surface').childFromName('Shader').getHistogramItem() self.bx.addHistogramItem('right', histogram_1) #set the main scatter plot of the counts self.sine_data_plot = self.cx.addPlot('Scatter', Name='Raw phase', Style=['s', '10']) self.sine_fit_2_plot = self.cx.addPlot('Scatter', Name='Fitted phase', Style=['-']) self.contrast_plot = self.dx.addPlot('Scatter', Name='Contrast', Style=['-', 's', '10']) self.ax.draw() self.bx.draw() self.cx.draw() self.dx.draw() self.ax.pointer.pointer_handler['Sticky'] = '2' self.bx.pointer.pointer_handler['Sticky'] = '2' self.cx.pointer.pointer_handler['Sticky'] = '3' self.dx.pointer.pointer_handler['Sticky'] = '3' self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[0][1][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[1][0][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[1][1][0].grid_layout.setMargin(0)
class PanelPageMaskWidget(PageMaskWidget): def __init__(self, stack, parent, mask_interface): PageMaskWidget.__init__(self, stack, parent, mask_interface) self.local_widget.setStyleSheet( "#mask_editor{background:transparent;}") self._threads = [] def link(self, mask_core, env): ''' This routine will link to the io manager class from the core. ''' self._resetPara() self._initialize() self.env = env self.data = self.env.current_data.returnAsNumpy() self.mask_core = mask_core self._populateSelectors() self._connectSelectors() def _resetPara(self): ''' Reset the parameter setting group ''' try: self.para_group.deleteLater() except: pass self.para_group = QtWidgets.QGroupBox(self.local_widget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.para_group.setSizePolicy(sizePolicy) self.mask_layout_control.addWidget(self.para_group) def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' #initialise the widgets self._live = False self.tree = self.mask_interface.getTreeView() self.mask_combo_box = self.mask_interface.getComboBox() self.add_mask_button = QtWidgets.QPushButton("+") self.remove_mask_button = QtWidgets.QPushButton("-") self.mask_tree_layout.addWidget(self.tree) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.mask_combo_box.setSizePolicy(size_policy) self.combo_layout.addWidget(self.mask_combo_box) self.combo_layout.addWidget(self.add_mask_button) self.combo_layout.addWidget(self.remove_mask_button) #initialise the graphs self.my_canvas = MultiCanvasItem(self.mask_widget_visual, grid=[[True, True], [True, True]], x_ratios=[1, 1], y_ratios=[1, 1], background="w", highlightthickness=0) #set the subplots as local self.ax = self.my_canvas.getSubplot(0, 0) self.ax.axes.label_handler['Active'] = [True, True, True, True] self.ax.axes.label_handler['Text'] = ['py', 'px', 'None', 'None'] self.bx = self.my_canvas.getSubplot(0, 1) self.bx.axes.label_handler['Active'] = [True, True, True, True] self.bx.axes.label_handler['Text'] = ['py', 'px', 'None', 'None'] self.cx = self.my_canvas.getSubplot(1, 0) self.cx.axes.label_handler['Active'] = [True, True, True, True] self.cx.axes.label_handler['Text'] = [ 'Intensity', 'Time channel', 'None', 'None' ] self.dx = self.my_canvas.getSubplot(1, 1) self.dx.axes.label_handler['Active'] = [True, True, True, True] self.dx.axes.label_handler['Text'] = [ 'Contrast', 'Echo Time', 'None', 'None' ] self.dx.axes.general_handler['Log'] = [True, False] self.dx.zoomer['Zoom fixed'] = [False, True] self.dx.zoomer['Zoom fixed range'] = [0, 1, 0, 1] #set the two bin self.first_surface_plot = self.ax.addPlot('Surface', Name='Data area') self.second_surface_plot = self.bx.addPlot('Surface', Name='Mask and Data area') histogram_0 = self.first_surface_plot.childFromName( 'Surface').childFromName('Shader').getHistogramItem() self.ax.addHistogramItem('right', histogram_0) histogram_1 = self.second_surface_plot.childFromName( 'Surface').childFromName('Shader').getHistogramItem() self.bx.addHistogramItem('right', histogram_1) #set the main scatter plot of the counts self.sine_data_plot = self.cx.addPlot('Scatter', Name='Raw phase', Style=['s', '10']) self.sine_fit_2_plot = self.cx.addPlot('Scatter', Name='Fitted phase', Style=['-']) self.contrast_plot = self.dx.addPlot('Scatter', Name='Contrast', Style=['-', 's', '10']) self.ax.draw() self.bx.draw() self.cx.draw() self.dx.draw() self.ax.pointer.pointer_handler['Sticky'] = '2' self.bx.pointer.pointer_handler['Sticky'] = '2' self.cx.pointer.pointer_handler['Sticky'] = '3' self.dx.pointer.pointer_handler['Sticky'] = '3' self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[0][1][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[1][0][0].grid_layout.setMargin(0) self.my_canvas.canvas_nodes[1][1][0].grid_layout.setMargin(0) def _populateSelectors(self): ''' populate the window layout. The grid is the main input of this method and all elements will be placed accordingly. ''' #Visual selector self._visual_data_raw = QtWidgets.QRadioButton("Raw data") self._visual_data_corrected = QtWidgets.QRadioButton("Corrected data") self._visual_button_group = QtWidgets.QButtonGroup(self.widget) self._visual_button_group.addButton(self._visual_data_raw, 0) self._visual_button_group.addButton(self._visual_data_corrected, 1) self.visual_select = QtWidgets.QHBoxLayout() self.visual_select.addWidget(self._visual_data_raw) self.visual_select.addWidget(self._visual_data_corrected) self.para_vbox = QtWidgets.QVBoxLayout() self.para_grid = QtWidgets.QGridLayout() self.para_vbox.addLayout(self.visual_select) self.para_vbox.addLayout(self.para_grid) self.para_vbox.addStretch(1) self.para_group.setLayout(self.para_vbox) #initialise the tab self.widget_list = [] #--- self.widget_list.append([ QtWidgets.QLabel('Parameter:', parent=self.para_group), 0, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 0, 1, 1, 1, None]) self.widget_list[-1][0].addItems( [str(val) for val in self.env.current_data.get_axis('Parameter')]) self.para_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Measurement:', parent=self.para_group), 1, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 1, 1, 1, 1, None]) self.widget_list[-1][0].addItems([ str(val) for val in self.env.current_data.get_axis('Measurement') ]) self.meas_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Echo time:', parent=self.para_group), 2, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [ScientificComboBox(parent=self.para_group), 2, 1, 1, 1, None]) self.widget_list[-1][0].addItems( self.env.current_data.get_axis('Echo Time')) self.echo_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Foil:'), 3, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 3, 1, 1, 1, None]) self.widget_list[-1][0].addItems( [str(val) for val in self.env.current_data.get_axis('Foil')]) self.foil_drop = self.widget_list[-1][0] #--- self.widget_list.append( [QtWidgets.QCheckBox('Log view:'), 4, 0, 1, 1, None]) self.log_view = self.widget_list[-1][0] self.widget_list.append([ QtWidgets.QCheckBox('Live refresh', parent=self.para_group), 4, 1, 1, 1, None ]) self.widget_list[-1][0].setChecked(False) self.widget_list.append([ QtWidgets.QPushButton('Compute', parent=self.para_group), 5, 1, 1, 1, None ]) self.compute_button = self.widget_list[-1][0] ############################################## #add the tabs for element in self.widget_list: self.para_grid.addWidget(element[0], element[1], element[2], element[3], element[4]) if not element[5] is None: element[0].setAlignment(element[5]) def _connectSelectors(self): ''' Set the selectors to their methods ''' self._visual_data_raw.clicked.connect(self._parseAndSend) self._visual_data_corrected.clicked.connect(self._parseAndSend) self.widget_list[1][0].currentIndexChanged.connect(self._parseAndSend) self.widget_list[3][0].currentIndexChanged.connect(self._parseAndSend) self.widget_list[5][0].currentIndexChanged.connect(self._parseAndSend) self.widget_list[7][0].currentIndexChanged.connect(self._parseAndSend) self.widget_list[10][0].clicked.connect(self._parseAndSendManual) self.widget_list[9][0].stateChanged.connect(self._setLive) def _setLive(self, num): ''' set the state of the live computation ''' if num == 2: self._live = True else: self._live = False def _parseAndSend(self): ''' This routine will simply grab the parameters of each of the mask widgets and parse it to the linked mask class ''' if not self.mask_core == None and self._live: self.mask_core.sendToGenerator(recreate=True) self.mask_core.generateMask(int(self.mask_input_x.text()), int(self.mask_input_y.text())) self._buildThread() def _parseAndSendManual(self): ''' This routine will simply grab the parameters of each of the mask widgets and parse it to the linked mask class ''' if not self.mask_core == None: self.mask_core.sendToGenerator(recreate=True) self.mask_core.generateMask(int(self.mask_input_x.text()), int(self.mask_input_y.text())) self._buildThread() def _updateGraph(self): ''' ''' self._updateVisual() def _buildThread(self): ''' the computation will be done in a thread and if not finished interupted to allow the UI to run smoothly ''' for i in range(len(self._threads))[::-1]: if self._threads[i][0].isFinished(): del self._threads[i] parameters = self._prepareThread() worker = PanelWorker(self.env.process.calcContrastSingle) worker.setParameters(*parameters) thread = QtCore.QThread() worker.moveToThread(thread) worker.finished.connect(self._updateVisual) worker.finished.connect(thread.quit) thread.started.connect(worker.run) thread.start() self._threads.append([thread, worker]) def _prepareThread(self): ''' the computation will be done in a thread and if not finished interupted to allow the UI to run smoothly ''' results = self.env.results.generateResult(name='Contrast mode') if self._visual_button_group.checkedId() == 0: self.env.process.calculateEcho() self.env.fit.noCorrection(self.env.current_data, self.env.results) self.data = self.env.results.getLastResult('Uncorrected Phase', 'Shift') results['Mode'] = 'Uncorrected' else: self.data = self.env.results.getLastResult('Corrected Phase', 'Shift') results['Mode'] = 'Corrected' results.setComplete() return [ self.data[self.widget_list[1][0].currentText()][int( float(self.widget_list[3][0].currentText()))][float( self.widget_list[5][0].currentData())][int( self.widget_list[7][0].currentText())], self.widget_list[1][0].currentText(), int(self.widget_list[7][0].currentText()), self.env.mask.mask, self.env.results, self.env.fit.para_dict['time_channels'] ] def _updateVisual(self): ''' Update the visual component from a thread ''' for i in range(len(self._threads))[::-1]: if self._threads[i][1]._finished: self.worker = self._threads[i][1] break try: para = self.worker.para data = self.worker.data process = self.worker.process counts = self.worker.counts fit = self.worker.fit except: return None x = np.arange(0, 128, 1) y = np.arange(0, 128, 1) x_1 = np.arange(0, 15, 0.01) #set the two bin self.first_surface_plot.setData(x=x, y=y, z=np.log10(np.sum(data, axis=(0)) + 1)) self.second_surface_plot.setData( x=x, y=y, z=np.log10(self.env.mask.mask * np.sum(data, axis=(0)) + 1)) #set the main scatter plot of the counts self.sine_data_plot.setData(x=np.array([i for i in range(len(counts))]), y=np.array(counts), error={ 'height': None, 'bottom': np.sqrt(counts), 'top': np.sqrt(counts) }) if not fit == None: self.sine_fit_2_plot.setData( x=x_1, y=fit['amplitude'] * np.cos(x_1 / 16. * 2 * np.pi + fit['phase']) + fit['mean']) if not process == None: self.contrast_plot.setData(x=process['Axis'][para], y=process['Contrast'][para]) self.ax.zoomer.zoom() self.bx.zoomer.zoom() self.cx.zoomer.zoom() self.dx.zoomer.zoom()
class PageMaskWidget(Ui_mask_editor): def __init__(self, stack, parent, mask_interface): Ui_mask_editor.__init__(self) #set the local pointers self.parent = parent self.stack = stack self.local_widget = QtWidgets.QWidget() self.mask_interface = mask_interface #build GUI self.setupUi(self.local_widget) self.para_group = QtWidgets.QGroupBox(self.local_widget) self._setup() self._initialize() self._connect() def _resetPara(self): ''' Reset the parameter setting group ''' try: self.para_group.deleteLater() except: pass self.para_group = QtWidgets.QGroupBox(self.local_widget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.para_group.setSizePolicy(sizePolicy) self.mask_layout_control.addWidget(self.para_group) def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' #initialise the widgets self.tree = self.mask_interface.getTreeView() self.mask_combo_box = self.mask_interface.getComboBox() self.add_mask_button = QtWidgets.QPushButton("+") self.remove_mask_button = QtWidgets.QPushButton("-") self.mask_tree_layout.addWidget(self.tree) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.mask_combo_box.setSizePolicy(size_policy) self.combo_layout.addWidget(self.mask_combo_box) self.combo_layout.addWidget(self.add_mask_button) self.combo_layout.addWidget(self.remove_mask_button) #initialise the graphs self.my_canvas = MultiCanvasItem(self.mask_widget_visual, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self.ax.axes.general_handler['Aspect ratio'] = [True, 1.] self.ax.pointer.pointer_handler['Sticky'] = 2 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.ax.draw() def _initialize(self): ''' Reset all the inputs and all the fields present in the current view. ''' self.mask_core = None self._plot_item = [] self.current_data = None def _connect(self): ''' Connect the interactive elements to their respective methods. ''' self.mask_button_add.clicked.connect(self.addItem) self.mask_button_remove.clicked.connect(self.removeItem) self.mask_interface.mask_updated.connect(self._parseAndSend) self.add_mask_button.clicked.connect(self.newMask) self.remove_mask_button.clicked.connect( self.mask_interface.removeCurrentMask) def _populateSelectors(self): ''' populate the window layout. The grid is the main input of this method and all elements will be placed accordingly. ''' #Visual selector self._visual_mask_pixel = QtWidgets.QRadioButton("View pixel mask") self._visual_mask_data = QtWidgets.QRadioButton("View data") self._visual_button_group = QtWidgets.QButtonGroup(self.widget) self._visual_button_group.addButton(self._visual_mask_pixel, 0) self._visual_button_group.addButton(self._visual_mask_data, 1) self.visual_select = QtWidgets.QHBoxLayout() self.visual_select.addWidget(self._visual_mask_pixel) self.visual_select.addWidget(self._visual_mask_data) self.para_vbox = QtWidgets.QVBoxLayout() self.para_grid = QtWidgets.QGridLayout() self.para_vbox.addLayout(self.visual_select) self.para_vbox.addLayout(self.para_grid) self.para_vbox.addStretch(1) self.para_group.setLayout(self.para_vbox) #initialise the tab self.widget_list = [] #--- self.widget_list.append([ QtWidgets.QLabel('Parameter:', parent=self.para_group), 0, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 0, 1, 1, 1, None]) self.widget_list[-1][0].addItems( [str(val) for val in self.env.current_data.get_axis('Parameter')]) self.para_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Measurement:', parent=self.para_group), 1, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 1, 1, 1, 1, None]) self.widget_list[-1][0].addItems([ str(val) for val in self.env.current_data.get_axis('Measurement') ]) self.meas_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Echo time:', parent=self.para_group), 2, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [ScientificComboBox(parent=self.para_group), 2, 1, 1, 1, None]) self.widget_list[-1][0].addItems( self.env.current_data.get_axis('Echo Time')) self.echo_drop = self.widget_list[-1][0] #--- self.widget_list.append([ QtWidgets.QLabel('Foil:'), 3, 0, 1, 1, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter ]) self.widget_list.append( [QtWidgets.QComboBox(parent=self.para_group), 3, 1, 1, 1, None]) self.widget_list[-1][0].addItems( [str(val) for val in self.env.current_data.get_axis('Foil')]) self.foil_drop = self.widget_list[-1][0] #--- self.widget_list.append( [QtWidgets.QCheckBox('Log view:'), 4, 1, 1, 1, None]) self.log_view = self.widget_list[-1][0] ############################################## #add the tabs for element in self.widget_list: self.para_grid.addWidget(element[0], element[1], element[2], element[3], element[4]) if not element[5] is None: element[0].setAlignment(element[5]) def _connectSelectors(self): ''' Set the selectors to their methods ''' self.widget_list[1][0].currentIndexChanged.connect(self._prepareData) self.widget_list[3][0].currentIndexChanged.connect(self._prepareData) self.widget_list[5][0].currentIndexChanged.connect(self._prepareData) self.widget_list[7][0].currentIndexChanged.connect(self._prepareData) self.widget_list[8][0].clicked.connect(self._prepareData) self._visual_mask_pixel.clicked.connect(self._handleVis) self._visual_mask_data.clicked.connect(self._handleVis) def _handleVis(self): ''' the computation will be done in a thread and if not finished interupted to allow the UI to run smoothly ''' if self._visual_button_group.checkedId() == 0: for child in self.widget_list: child[0].setVisible(False) self._updateGraph() else: for child in self.widget_list: child[0].setVisible(True) self._prepareData() def _prepareData(self): ''' the computation will be done in a thread and if not finished interupted to allow the UI to run smoothly ''' ############################################## #grab the parameters from the UI para = self.env.current_data.get_axis( self.env.current_data.axes.names[0])[self.widget_list[1] [0].currentIndex()] meas = self.env.current_data.get_axis( self.env.current_data.axes.names[1])[self.widget_list[3] [0].currentIndex()] echo = self.env.current_data.get_axis( self.env.current_data.axes.names[2])[self.widget_list[5] [0].currentIndex()] foil = self.env.current_data.get_axis( self.env.current_data.axes.names[3])[self.widget_list[7] [0].currentIndex()] ############################################## #process index para_idx = self.env.current_data.get_axis_idx( self.env.current_data.axes.names[0], para) meas_idx = self.env.current_data.get_axis_idx( self.env.current_data.axes.names[1], meas) echo_idx = self.env.current_data.get_axis_idx( self.env.current_data.axes.names[2], echo) foil_idx = self.env.current_data.get_axis_idx( self.env.current_data.axes.names[3], foil) data = self.data[para_idx, meas_idx, echo_idx, foil_idx, :] data = np.sum(data, axis=(0)) if self.log_view.isChecked(): data = np.log10(data + 1) self.current_data = data self._updateGraph() def newMask(self): ''' This routine will create an input dialog and then get it ''' text, ok = QtWidgets.QInputDialog.getText(self.widget, 'New mask name', 'Name of the new mask:') if ok: self.mask_interface.insertNewMask(text) def link(self, mask_core, env): ''' This routine will link to the io manager class from the core. ''' self._resetPara() self._initialize() self.env = env self.data = self.env.current_data.returnAsNumpy() self.mask_core = mask_core self._populateSelectors() self._connectSelectors() def unlink(self): ''' To remove the item ''' self.mask_core = None def addItem(self): ''' Add an element into the list which is loaded from a custom widget. If the element is part of the default series create a new one called by the default name with the appendix '_mod' ''' self.mask_interface.addItem() def removeItem(self): ''' Add an element into the list which is loaded from a custom widget. ''' index = self.tree.selectionModel().currentIndex() self.mask_interface.removeItem(index.row()) def _parseAndSend(self): ''' This routine will simply grab the parameters of each of the mask widgets and parse it to the linked mask class ''' if not self.mask_core == None: self.mask_core.sendToGenerator(recreate=True) self.mask_core.generateMask(int(self.mask_input_x.text()), int(self.mask_input_y.text())) self._updateGraph() def _checkUpdateNeed(self): ''' Check what has to be actually updated ''' if len(self._plot_item) != self.tree.model().root()._children: self.ax.clear() self.mask_plot = self.ax.addPlot('Surface', Name='Mask area') self._plot_item = [] for child in self.tree.model().root()._children: self._plot_item.append(self.ax.addItem(child._value)) self.ax.draw() else: for i, child in enumerate(self.tree.model().root()._children): if child._value != self._plot_item[i]._name: self.ax.removeItem(self._plot_item[i]) self._plot_item[i] = self.ax.addItem(child._value) def _updateGraph(self): ''' ''' self._checkUpdateNeed() for i, child in enumerate(self.tree.model().root()._children): self._plot_item[i].load(child.save()) if self._visual_button_group.checkedId() == 0: self.mask_plot.setData( x=np.array( [i for i in range(self.mask_core.mask_gen.mask.shape[0])]), y=np.array( [i for i in range(self.mask_core.mask_gen.mask.shape[1])]), z=self.mask_core.mask_gen.mask) elif not self.current_data is None: self.mask_plot.setData( x=np.array( [i for i in range(self.mask_core.mask_gen.mask.shape[0])]), y=np.array( [i for i in range(self.mask_core.mask_gen.mask.shape[1])]), z=self.current_data) def saveSingle(self): ''' ''' filters = "mask_save.txt" file_path = QtWidgets.QFileDialog.getSaveFileName( self.parent.window, 'Select file', filters)[0] if not file_path == '': self.mask_core.saveSingleMask(os.path.abspath(file_path)) def saveMultiple(self): ''' ''' filters = "masks_save.txt" file_path = QtWidgets.QFileDialog.getSaveFileName( self.parent.window, 'Select file', filters)[0] if not file_path == '': self.mask_core.saveAllMasks(os.path.abspath(file_path)) def loadSingle(self): ''' ''' filters = "*.txt" file_path = QtWidgets.QFileDialog.getOpenFileName( self.parent.window, 'Select file', filters)[0] if not file_path == '': self.mask_core.loadSingleMask(os.path.abspath(file_path)) def loadMultiple(self): ''' ''' filters = "*.txt" file_path = QtWidgets.QFileDialog.getOpenFileName( self.parent.window, 'Select file', filters)[0] if not file_path == '': self.mask_core.loadAllMasks(os.path.abspath(file_path))
class DisplayFoilWindowLayout(Ui_foil_display): ''' This class will manage the raw import machinery. the UI is inherited through Ui_main_window from the Qt designer anf then converted through pyuic5 ''' def __init__(self, window, window_manager): Ui_foil_display.__init__(self) self.window_manager = window_manager self.window = window self.setup() def setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area ''' self.setupUi(self.window) self.my_canvas = MultiCanvasItem(self.graph_widget, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) ax = self.my_canvas.getSubplot(0, 0) ax.pointer.pointer_handler['Sticky'] = 2 def link(self, instrument): ''' This routine will link to the io manager class from the core. ''' self._instrument = instrument self.foil_detector_label.setText( self._instrument.detector.identifier + ' (' + self._instrument.detector.current_date + ')') self.initialize() self.connect() def initialize(self): ''' This routine will link to the io manager class from the core. ''' self.foil_spin.setMinimum(0) self.foil_spin.setMaximum( self._instrument.detector.foil_array.shape[0] - 1) self.ax = self.my_canvas.getSubplot(0, 0) self.plot = self.ax.addPlot('Surface', Name='Surface') histogram = self.plot.childFromName('Surface').childFromName( 'Shader').getHistogramItem() self.ax.addHistogramItem('right', histogram) self.ax.draw() self.draw() self.connect() def connect(self): ''' This routine will link to the io manager class from the core. ''' self.foil_spin.valueChanged.connect(self.draw) self.foil_factor_spin.valueChanged.connect(self.draw) def draw(self): ''' ''' data = self._instrument.detector.foil_array[ self.foil_spin.value()] * self.foil_factor_spin.value() self.plot.setData(x=np.array([i for i in range(data.shape[0])]), y=np.array([i for i in range(data.shape[1])]), z=data)
class PageResultWidget(Ui_result_widget): def __init__(self, stack, parent): Ui_result_widget.__init__(self) self.parent = parent self.stack = stack self.local_widget = QtWidgets.QWidget() self.env_handler = None self._setup() self._connect() def _setup(self): ''' This is the initial setup method that will build the layout and introduce the graphics area. ''' self.setupUi(self.local_widget) self.process_tree = ResultTree(self.data_group) self.verticalLayout_4.addWidget(self.process_tree) self.horizontalLayout = QtWidgets.QHBoxLayout() self.process_refresh_button = QtWidgets.QPushButton( 'Refresh', self.data_group) self.process_refresh_button.setObjectName("process_refresh_button") self.horizontalLayout.addWidget(self.process_refresh_button) self.verticalLayout_4.addLayout(self.horizontalLayout) self.process_list_plot = PlotTree(self.plot_items_group) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.process_list_plot.sizePolicy().hasHeightForWidth()) self.verticalLayout_2.addWidget(self.process_list_plot) self.my_canvas = MultiCanvasItem(self.process_widget_plot, grid=[[True]], x_ratios=[1], y_ratios=[1], background="w", highlightthickness=0) self.ax = self.my_canvas.getSubplot(0, 0) self.ax.pointer.pointer_handler['Sticky'] = 3 self.my_canvas.canvas_nodes[0][0][0].grid_layout.setMargin(0) self.result_handler_ui = ResultHandlerUI(self, self.process_tree, self.process_list_plot) def _connect(self): ''' Connect all Qt slots to their respective methods. ''' self.result_handler_ui.result_model.dataChanged.connect( self._resize_tree) self.process_refresh_button.clicked.connect( self.result_handler_ui.refreshDict) self.process_list_plot.dropAccepted.connect( self.result_handler_ui.processDrop) self.process_list_plot.clicked.connect( self.result_handler_ui.setPlotItem) self.remove_plot.clicked.connect( self.result_handler_ui.removePlotElements) self.reset_intern.clicked.connect( self.result_handler_ui.removeAllIntElement) self.reset_external.clicked.connect( self.result_handler_ui.removeAllExtElement) self.process_button_plot_plot.clicked.connect(self._updatePlot) self.set_rainbow.clicked.connect(self.result_handler_ui.setRainbow) self.process_check_log_x.clicked.connect(self.manageLog) self.process_check_log_y.clicked.connect(self.manageLog) self.my_canvas._model.dataChanged.connect(self.setLog) def _resize_tree(self): ''' process with the log ''' self.process_tree.resizeColumnToContents(0) def manageLog(self): ''' process with the log ''' self.my_canvas._model.dataChanged.disconnect(self.setLog) self.ax.axes.general_handler['Log'] = [ self.process_check_log_x.isChecked(), self.process_check_log_y.isChecked() ] self.my_canvas._model.dataChanged.connect(self.setLog) def setLog(self): ''' process with the log ''' self.process_check_log_x.setChecked( self.ax.axes.general_handler['Log'][0]) self.process_check_log_y.setChecked( self.ax.axes.general_handler['Log'][1]) def link(self, env_handler=None): ''' Link the GUI to the environment that will be read and taken care of. ''' if not env_handler == None: self.env_handler = env_handler self.result_handler_ui.link(env_handler) def _updatePlot(self): ''' ''' self.ax.clear() #get the instructions instructions = self.result_handler_ui._processPlot() #set up the offsets idx = 0 for key in instructions.keys(): if self.process_check_offset.isChecked( ) and instructions[key]['link'] == None: instructions[key][ 'offset'] += self.process_spin_offset_total.value( ) + idx * self.process_spin_offset.value() idx += 1 for key in instructions.keys(): if not instructions[key]['link'] == None and instructions[key][ 'link'] in instructions.keys(): instructions[key]['offset'] = instructions[instructions[key] ['link']]['offset'] #plot all for key in instructions.keys(): if len(instructions[key]['style']) == 0: pass elif not 'y' in instructions[key].keys(): pass elif not 'x' in instructions[key].keys( ) and not 'e' in instructions[key].keys(): self._plotSingleY(instructions[key], key) elif 'x' in instructions[key].keys( ) and not 'e' in instructions[key].keys(): self._plotDoubleY(instructions[key], key) elif 'x' in instructions[key].keys( ) and 'e' in instructions[key].keys(): self._plotTripleY(instructions[key], key) self.ax.draw() def _plotSingleY(self, instruction, key): ''' Plot a curve where only the y axes is defined. ''' y = instruction['y'] x = np.array([i for i in range(len(y))]) self.ax.addPlot('Scatter', Name=key, x=x, y=y + instruction['offset'], Style=instruction['style'], Thickness=instruction['thickness'], Color=instruction['color']) def _plotDoubleY(self, instruction, key): ''' Plot a curve where only the y and x axes are defined. ''' y = instruction['y'] x = instruction['x'] sort_idx = x.argsort() self.ax.addPlot('Scatter', Name=key, x=x[sort_idx], y=y[sort_idx] + instruction['offset'], Style=instruction['style'], Thickness=instruction['thickness'], Color=instruction['color']) def _plotTripleY(self, instruction, key): ''' Plot a curve where all axes are defined. ''' y = instruction['y'] x = instruction['x'] e = instruction['e'] sort_idx = x.argsort() error = { 'height': None, 'width': None, 'bottom': e[sort_idx], 'top': e[sort_idx] } self.ax.addPlot('Scatter', Name=key, x=x[sort_idx], y=y[sort_idx] + instruction['offset'], error=error, Style=instruction['style'], Thickness=instruction['thickness'], Color=instruction['color'])