def draw(self, dataset, zoom_reset=False): """ Draw 1D or 2D dataset corresponding to the current dataset. Parameters ---------- zoom_reset: bool, optional True if the x and y range must be reset to the full range when redrawing. """ self.dataset = dataset if self._autorange: zoom_reset = True # Create the main plotItem if not hasattr(self, 'p'): vb = CustomViewBox(ndim=dataset.ndim, prefs=dataset.preferences) self.p = self.addPlot(row=0, col=0, viewBox=vb) # Draw main data scp.debug_('>>>>>>>>>> Draw') self._draw(zoom_reset=zoom_reset) # Draw processed self._draw_processed(zoom_reset=zoom_reset) self._autorange = False
def removeDataset(self, name=None): # Confirm if '/original' in name: name = name.split('/')[0] if not confirm_msg(self.parent, 'Remove', f'Removing the main (original) datset will ' f'remove all other datasets present in `{name}`.\n' f'Is-it what you want?'): return elif not confirm_msg(self.parent, 'Remove', f'Do you really want to remove the `{name}` dataset?'): return scp.debug_(f'remove: {name}') self.sigDatasetChanged.emit(None, 'deselect') if name in self.project.projects_names and self.project[name].implements('Project'): # its the whole subproject to be removed self.project.remove_project(name) else: try: subproject, name = name.split('/') subproject.remove_dataset(name) except: self.project.remove_dataset(name) self.dataset = None self.dirty = True # Signal self.sigProjectChanged.emit('dataset removed')
def saveProject(self, *args, **kwargs): if not kwargs.pop('force', False): if not self.dirty: return scp.debug_('Saving project') # we need to save only the original data as they will be recalculaded anyway when reloaded proj = self.project.copy() for name in proj.projects_names: for datasetname in proj[name].datasets_names: if 'original' not in datasetname: proj[name].remove_dataset(datasetname) else: proj[name][datasetname].processeddata = None proj[name][datasetname].processedmask = False transposed = self.project[name][datasetname].transposed # we take the flag on the self.project # has it is not copied if transposed: proj[name][datasetname].transpose(inplace=True) if proj.directory is None: proj._directory = self._directory if kwargs.get('saveas') or proj.name == 'untitled': proj.save_as(self._directory / 'untitled.pscp', Qt_parent=self.parent) self.sigProjectChanged.emit('renamed') else: proj.save() scp.preferences.last_project = Path(proj.directory) / proj.name self.dirty = False
def getProcessingActions(self, params): # Brute force method: if any of the processing parameters change, we reevaluate all processing step (will # be refined later) proc = params.param('processing') actions = [] for item in proc: if not item.value(): # item not checked, we do not take it into account continue actions.append([item.opts['action']]) parameters = {} if not item.name().startswith('define regions'): if item.childs: for children in item.childs: parameters[children.name()] = children.value() else: parameters['kind'] = item.param('kind').value() parameters['range'] = [ list(eval(val.value().split('> ')[1])) for val in item.param('regiongroup').children() ] actions[-1].append(parameters) scp.debug_('ACTIONS: ') scp.debug_(actions) return actions
def __init__(self, **opts): opts['type'] = 'group' opts['addText'] = "Add new ..." super().__init__(**opts) scp.debug_('New region group added') self.sigChildAdded.connect(self.addRegion) self.current_index = 0
def addNew(self, key): item = self.processors[key] name = f"{key}#{self.current_index}" item['title'] = f"{key}{' '*(20 - len(key))}" item['name'] = name child = self.insertChild(len(self.childs) - 1, item) scp.debug_(f"New processor added: {name}") self.current_index += 1 return child
def initialize(self, dataset): if dataset is None: self._dataset = None self._params = None return scp.debug_('initialize controller') self.isInitializing = True params = self.params if params is None or not dataset.state: ndim = dataset._squeeze_ndim processing = ProcessGroup( name='processing', title='Processing pipeline', children=[getProcessors('basis')['output']]) params = [processing] scp.debug_('create group') # Create tree of Parameter objects params = Parameter.create(name='params', type='group', children=params) params._parent = self self.setParameters(params, showTop=False) if dataset.state: scp.debug_('Restore state') # was already saved before. Restore it params.restoreState(dataset.state, blockSignals=True) # actualise scp.debug_('Save state') dataset.state = params.saveState() dataset = self.performProcessing(dataset, params) for item in params.param('processing'): item.opts['expanded'] = False self._params = params # set the current dataset self._dataset = dataset # connects events self._params.sigTreeStateChanged.connect(self.change) self.isInitializing = False scp.debug_('Initialisation finished')
def emitSelectDataset(self, *args, **kwargs): """ When an item is clicked in the project window, some actions can be performed, e.g., plot the corresponding data. """ sel = self.currentItem() if sel: # make a plot of the data id = sel.text(2) name = sel.text(0) if sel.text(1) == "Project": if name == self.project.name: return name = f'{name}/original' scp.debug_(f'---------------------- Dataset {name}({id}) selected') self.sigDatasetSelected.emit(name)
def __init__(self, parent): QtCore.QObject.__init__(self) self._parent = parent # Autosave feature self.autosaveTimer = QtCore.QTimer() self.autosaveTimer.setInterval(30000) self.autosaveTimer.timeout.connect(self.saveProject) # Open last_project last_project = scp.preferences.last_project if last_project: last_project = Path(last_project).with_suffix(".pscp") if scp.preferences.autoload_project and last_project is not None and last_project.exists(): scp.debug_(f'Open last project {last_project}') self.project = last_project else: self.openProject(new=True)
def updateDataset(self, dataset): if 'untitled' not in dataset.name: # the parent subproject should be specified subproj = dataset.name.split('/')[0] if dataset.name in self.project[subproj].datasets_names: # In this case just update : but warning the dataset id must be the same the previous one. scp.debug_(f'Update dataset: {dataset.name}') id = self.project[subproj]._datasets[dataset.name].id dataset._id = id self.project[subproj]._datasets[dataset.name] = dataset if self.dataset.name == dataset.name: self.sigDatasetChanged.emit(dataset, 'updated') else: scp.debug_(f'Add dataset {dataset.name} to project') self.project[subproj].add_dataset(dataset) self.sigProjectChanged.emit('dataset added') #self.sigDatasetChanged.emit(dataset, 'added') self.dirty = True
def addDataset(self, dataset=None): scp.debug_('Add a dataset') # Read the dataset try: if not dataset: dataset = scp.read(Qt_parent=self.parent, default_filter='omnic') if dataset is None: # still not determined. return except Exception as e: scp.error_(e) # Create a subproject with this dataset subproj = scp.Project() self.project.add_project(subproj, dataset.name) subproj.add_dataset(dataset, f'{dataset.name}/original') # Signal self.dirty = True self.sigProjectChanged.emit('dataset added')
def change(self, params, changes): dataset = self.dataset if self.isProcessing or self.isInitializing or dataset is None: return state = params.saveState() if dataset.state != state: dataset.state = state self.parent.project.dirty = True # variable elif changes[0][1] != 'contextMenu': return for param, change, data in changes: if change == 'parent' and data is None: # when an element is removed self.parent.plotwidget.draw(dataset, False) return # Name of the parameter or group changed name = param.name() scp.debug_(f'{name} changed `{changes}`') # parents? top_group = param top_parent = param.parent() if top_parent is None: return while top_parent.name() != 'params': top_group = top_parent top_parent = top_parent.parent() # actions if top_group.name() == 'processing': scp.debug_('processing changed -> execute actions') self.processingChanged(dataset, params, param, change, data) return
def propagateActions(self, dataset, actions): if actions is None or actions == [None]: # Only output, but set to None return # input new = dataset.copy() # apply actions nprocess = 0 for action in actions: if action is None: continue nprocess += 1 scp.debug_(f'Action running: {action}') cmdtxt = action[0].split('.') if len(cmdtxt) > 1: # call from a library or a script to import lib = import_module(cmdtxt[0]) f = cmdtxt[1] else: lib = self f = cmdtxt[0] func = getattr(lib, f) kwargs = action[1] new = func(new, **kwargs) if nprocess and new is not None: dataset.processeddata = new.data dataset.processedmask = new.mask if new.transposed: # in this case the original data must also be transposed dataset.transpose(inplace=True) else: dataset.processeddata = None dataset.processedmask = False return dataset
def addRegion(self, param, child, pos): kind = self.parent().param('kind').value() if child.value() == 'undefined': # dimension dim = self.parent().parent().parent().parent().dataset.dims[-1] # default span rangex = np.array(self.parent().parent().parent().parent().parent. plotwidget.p.getAxis('bottom').range) x = rangex.mean() w = rangex.ptp() / 50 span = (x - w, x + w) else: dim, span = child.value().split('> ') span = eval(span) # add it self.parent().regions.addRegion(child, kind=kind, span=span, dim=dim) scp.debug_( f'> new {kind} region added to the regions (index: {self.current_index})' )
def onDatasetChanged(self, dataset, change=None): if dataset is None or change == 'select': if hasattr(self.parent, 'plotwidget'): self.parent.plotwidget.close() del self.parent.plotwidget self.parent.dplot.hideTitleBar() self.clear() if change != 'select': return scp.debug_(f'Update controller: {dataset.name}') # Update the controller if change == 'select': self._params = None self.initialize(dataset) # Redraw self.parent.setupPlot(title=dataset.name) self.parent.plotwidget.draw(dataset, zoom_reset=True)
def restoreState(self, state, **kwargs): # remove processing children but output. They will be restored latter state_children = OrderedDict() for key in list(state['children'].keys())[:]: item = state['children'][key] if key != 'output': state_children[key] = item del state['children'][key] super().restoreState(state, **kwargs) # now we can add the define region entries for key in state_children.keys(): item, _ = key.split('#') child = self.addNew(item) child.setOpts(value=state_children[key]['value']) child.setOpts(expanded=state_children[key]['expanded']) if item == 'define regions': # set the stored kind to this new child child.param('kind').setValue( state_children[key]['children']['kind']['value']) if child.param('kind').value() != 'undefined': child.param('kind').setOpts(readonly=True) # now we need to add the children ranges try: for item in state_children[key]['children']['regiongroup'][ 'children'].values(): span = child.param('regiongroup').addNew( span=item['value']) span.parent().setOpts( expanded=state_children[key]['children'] ['regiongroup']['expanded']) except KeyError: continue scp.debug_('ProcessGroup restored')
def test_logger(caplog): logger = logging.getLogger("SpectroChemPy") logger.propagate = True caplog.set_level(DEBUG) # We can set the level using strings set_loglevel("DEBUG") assert logger.handlers[0].level == INFO # DEBUG only on the file assert logger.handlers[1].level == DEBUG set_loglevel(WARNING) assert logger.handlers[0].level == WARNING assert logger.handlers[1].level == WARNING error_("\n" + "*" * 80 + "\n") debug_("debug in WARNING level - should not appear") info_("info in WARNING level - should not appear") warning_("OK this is a Warning") error_("OK This is an Error") error_("\n" + "*" * 80 + "\n") set_loglevel(INFO) assert logger.handlers[0].level == INFO assert logger.handlers[1].level == INFO debug_("debug in INFO level - should not appear on stdout") info_("OK - info in INFO level") warning_("OK this is a Warning") error_("OK This is an Error") error_("\n" + "*" * 80 + "\n") set_loglevel("DEBUG") assert logger.handlers[0].level == INFO assert logger.handlers[1].level == DEBUG debug_("OK - debug in DEBUG level") info_("OK - info in DEBUG level") assert caplog.records[-1].levelname == "INFO" assert caplog.records[-1].message.endswith("OK - info in DEBUG level") warning_("OK this is a Warning") assert caplog.records[-1].levelname == "WARNING" assert caplog.records[-1].message.endswith("OK this is a Warning") error_("OK This is an Error") assert caplog.records[-1].levelname == "ERROR" assert caplog.records[-1].message.endswith("OK This is an Error")
def test_logger(caplog): logger = logging.getLogger('SpectroChemPy') logger.propagate = True caplog.set_level(logging.DEBUG) # We can set the level using strings set_loglevel("DEBUG") assert logger.level == logging.DEBUG set_loglevel(WARNING) assert logger.level == logging.WARNING error_('\n' + '*' * 80 + '\n') debug_('debug in WARNING level - should not appear') info_('info in WARNING level - should not appear') warning_('OK this is a Warning') error_('OK This is an Error') error_('\n' + '*' * 80 + '\n') set_loglevel(INFO) assert logger.level == logging.INFO debug_('debug in INFO level - should not appear') info_('OK - info in INFO level') warning_('OK this is a Warning') error_('OK This is an Error') error_('\n' + '*' * 80 + '\n') set_loglevel('DEBUG') assert logger.level == logging.DEBUG debug_('OK - debug in DEBUG level') info_('OK - info in DEBUG level') assert caplog.records[-1].levelname == 'INFO' assert caplog.records[-1].message == 'OK - info in DEBUG level' warning_('OK this is a Warning') assert caplog.records[-1].levelname == 'WARNING' assert caplog.records[-1].message == 'OK this is a Warning' error_('OK This is an Error') assert caplog.records[-1].levelname == 'ERROR' assert caplog.records[-1].message == 'OK This is an Error'
pass # %% [markdown] # ## API Configuration # # Many options of the API can be set up # %% scp.set_loglevel(scp.INFO) # %% [markdown] # In the above cell, we have set the **log** level to display ``info`` messages, such as this one: # %% scp.info_('this is an info message!') scp.debug_('this is a debug message!') # %% [markdown] # Only the info message is displayed, as expected. # # If we change it to ``DEBUG``, we should get the two messages # %% scp.set_loglevel(scp.DEBUG) scp.info_('this is an info message!') scp.debug_('this is a debug message!') # %% [markdown] # Let's now come back to a standard level of message for the rest of the Tutorial.
# %% [markdown] # And finally, the next instructions reset the loglevel to `WARNING` level (default), and print it. # As seen below, no message `changed default log_level to ...` is delivered # %% scp.set_loglevel("WARNING") # reset to default print(f"New loglevel: {scp.get_loglevel()}") # %% [markdown] # It is also possible to issue such messages in scripts. In the cell below, we set the loglevel to `INFO` and try to # print two types of messages: # %% scp.set_loglevel("INFO") scp.info_("this is an info message!") scp.debug_("this is a debug message!") # %% [markdown] # As expected, only the info message was displayed. # # If we change the loglevel to ``DEBUG``, then the two messages will be printed: # %% scp.set_loglevel(scp.DEBUG) scp.info_("this is an info message!") scp.debug_("this is a debug message!") # %% [markdown] # Finally, we come back to the standard level of message for the rest of the Tutorial -- in this case neither `DEBUG` # nor `INFO` messages will be printed.
def editname(self, *args): # TODO: editing name scp.debug_(args)