def __init__(self): super().__init__() dbox = gui.widgetBox(self.controlArea, "Image values") rbox = gui.radioButtons( dbox, self, "value_type", callback=self._change_integration) gui.appendRadioButton(rbox, "From spectra") self.box_values_spectra = gui.indentedBox(rbox) gui.comboBox( self.box_values_spectra, self, "integration_method", valueType=int, items=(a.name for a in self.integration_methods), callback=self._change_integral_type) gui.rubber(self.controlArea) gui.appendRadioButton(rbox, "Use feature") self.box_values_feature = gui.indentedBox(rbox) self.feature_value_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.feature_value = gui.comboBox( self.box_values_feature, self, "attr_value", callback=self.update_feature_value, model=self.feature_value_model, sendSelectedValue=True, valueType=str) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.imageplot = ImagePlot(self) self.imageplot.selection_changed.connect(self.output_image_selection) self.curveplot = CurvePlotHyper(self, select=SELECTONE) self.curveplot.selection_changed.connect(self.redraw_data) self.curveplot.plot.vb.x_padding = 0.005 # pad view so that lines are not hidden splitter.addWidget(self.imageplot) splitter.addWidget(self.curveplot) self.mainArea.layout().addWidget(splitter) self.line1 = MovableVline(position=self.lowlim, label="", report=self.curveplot) self.line1.sigMoved.connect(lambda v: setattr(self, "lowlim", v)) self.line2 = MovableVline(position=self.highlim, label="", report=self.curveplot) self.line2.sigMoved.connect(lambda v: setattr(self, "highlim", v)) self.line3 = MovableVline(position=self.choose, label="", report=self.curveplot) self.line3.sigMoved.connect(lambda v: setattr(self, "choose", v)) for line in [self.line1, self.line2, self.line3]: line.sigMoveFinished.connect(self.changed_integral_range) self.curveplot.add_marking(line) line.hide() self.data = None self.disable_integral_range = False self.resize(900, 700) self._update_integration_type() # prepare interface according to the new context self.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0]))
def __init__(self, parent=None, **kwargs): limits = kwargs.pop('limits', None) label = kwargs.pop('label', None) delete = kwargs.pop('delete', True) super().__init__(parent, **kwargs) minf, maxf = -sys.float_info.max, sys.float_info.max if label: self.addWidget(QLabel(label)) self.lowlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[0], maximumWidth=75) self.highlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[1], maximumWidth=75) self.lowlime.setValue(limits[0]) self.highlime.setValue(limits[1]) self.addWidget(self.lowlime) self.addWidget(self.highlime) if delete: self.button = QPushButton( QApplication.style().standardIcon( QStyle.SP_DockWidgetCloseButton), "") self.addWidget(self.button) self.button.clicked.connect(self.selfDelete) self.lowlime.valueChanged[float].connect(self.limitChanged) self.highlime.valueChanged[float].connect(self.limitChanged) self.lowlime.editingFinished.connect(self.editFinished) self.highlime.editingFinished.connect(self.editFinished) self.lowlime.focusIn = self.focusInChild self.highlime.focusIn = self.focusInChild self.line1 = MovableVline(position=limits[0], label=label + " - Low") self.line1.sigMoved.connect(self.lineLimitChanged) self.line2 = MovableVline(position=limits[1], label=label + " - High") self.line2.sigMoved.connect(self.lineLimitChanged) self.line1.sigMoveFinished.connect(self.editFinished) self.line2.sigMoveFinished.connect(self.editFinished)
def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QFormLayout() self.controlArea.setLayout(layout) minf, maxf = -sys.float_info.max, sys.float_info.max self.__values = {} self.__editors = {} self.__lines = {} for name, longname in self.integrator.parameters(): v = 0. self.__values[name] = v e = SetXDoubleSpinBox(decimals=4, minimum=minf, maximum=maxf, singleStep=0.5, value=v) e.focusIn = self.activateOptions e.editingFinished.connect(self.edited) def cf(x, name=name): self.edited.emit() return self.set_value(name, x) e.valueChanged[float].connect(cf) self.__editors[name] = e layout.addRow(name, e) l = MovableVline(position=v, label=name) l.sigMoved.connect(cf) self.__lines[name] = l self.focusIn = self.activateOptions self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.user_changed = False
def __init__(self, parent=None, **kwargs): limits = kwargs.pop('limits', None) label = kwargs.pop('label', None) delete = kwargs.pop('delete', True) super().__init__(parent, **kwargs) minf, maxf = -sys.float_info.max, sys.float_info.max if label: self.addWidget(QLabel(label)) self.lowlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[0], maximumWidth=75) self.highlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[1], maximumWidth=75) self.lowlime.setValue(limits[0]) self.highlime.setValue(limits[1]) self.addWidget(self.lowlime) self.addWidget(self.highlime) if delete: self.button = QPushButton( QApplication.style().standardIcon(QStyle.SP_DockWidgetCloseButton), "") self.addWidget(self.button) self.button.clicked.connect(self.selfDelete) self.lowlime.valueChanged[float].connect(self.limitChanged) self.highlime.valueChanged[float].connect(self.limitChanged) self.lowlime.editingFinished.connect(self.editFinished) self.highlime.editingFinished.connect(self.editFinished) self.lowlime.focusIn = self.focusInChild self.highlime.focusIn = self.focusInChild self.line1 = MovableVline(position=limits[0], label=label + " - Low") self.line1.sigMoved.connect(self.lineLimitChanged) self.line2 = MovableVline(position=limits[1], label=label + " - High") self.line2.sigMoved.connect(self.lineLimitChanged) self.line1.sigMoveFinished.connect(self.editFinished) self.line2.sigMoveFinished.connect(self.editFinished)
def __init__(self): super().__init__() self.v = Decimal(1111) le = lineEditFloatRange(self, self, "v") self.controlArea.layout().addWidget(le) self.vplus = Decimal(0) le100 = lineEditFloatRange(self, self, "vplus") self.controlArea.layout().addWidget(le100) self.add = Decimal(100) def refresh(): self.v = self.v # just set one main so that dependant values are refreshed # self.vplus = self.vplus # this would have the opposite effect leadd = lineEditFloatRange(self, self, "add", callback=refresh) self.controlArea.layout().addWidget(leadd) connect_settings(self, "v", "vplus", transform=PlusAdd(self)) # # add MovableVLines ajd test this with spectra # self.curveplot = CurvePlot(self) self.mainArea.layout().addWidget(self.curveplot) self.curveplot.set_data(Orange.data.Table("collagen")) self.line1 = MovableVline(label="Value") connect_line(self.line1, self, "v") self.line2 = MovableVline(label="Value + something") connect_line(self.line2, self, "vplus") self.curveplot.add_marking(self.line1) self.curveplot.add_marking(self.line2)
def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QGridLayout() layout.setSpacing(2) self.controlArea.setLayout(layout) self.__values = {} self.__editors = {} self.__lines = {} m = self.model() for name, value in m.def_vals.items(): m.set_param_hint(name, value=value) self.__defaults = m.param_hints for row, name in enumerate(self.model_parameters()): h = copy.deepcopy(self.__defaults.get(name, OrderedDict(value=0))) self.__values[name] = h e = ParamHintBox(h) e.focus_in = self.activateOptions e.editingFinished.connect(self.edited) def change_hint(h, name=name): self.edited.emit() return self.set_param_hints(name, h) e.valueChanged.connect(change_hint) self.__editors[name] = e layout.addWidget(QLabel(name), row, 0) layout.addWidget(e, row, 1) if name in self.model_lines(): l = MovableVline(position=0.0, label=name) def change_value(x, name=name): self.edited.emit() return self.set_hint(name, value=x) l.sigMoved.connect(change_value) self.__lines[name] = l self.focusIn = self.activateOptions self.user_changed = False
def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QGridLayout() layout.setSpacing(2) self.controlArea.setLayout(layout) self.__values = {} self.__editors = {} self.__lines = {} for row, name in enumerate(self.model_parameters()): h = copy.deepcopy(self.defaults().get(name, {})) set_default_vary(h) self.__values[name] = h e = ParamHintBox(h) e.focus_in = self.activateOptions def change_hint(name=name): self.edited.emit() self.changed_param_hints(name) e.valueChanged.connect(change_hint) self.__editors[name] = e layout.addWidget(QLabel(name), row, 0) layout.addWidget(e, row, 1) if name in self.model_lines(): l = MovableVline(position=0.0, label=name) def change_value(_, line=l, name=name): self.set_hint(name, "value", float(line.rounded_value())) self.__editors[name].update_min_max_for_delta() self.edited.emit() l.sigMoved.connect(change_value) self.__lines[name] = l self.focusIn = self.activateOptions self.user_changed = False
class OWHyper(OWWidget): name = "HyperSpectra" class Inputs: data = Input("Data", Orange.data.Table, default=True) class Outputs: selected_data = Output("Selection", Orange.data.Table, default=True) annotated_data = Output(ANNOTATED_DATA_SIGNAL_NAME, Orange.data.Table) icon = "icons/hyper.svg" priority = 20 replaces = ["orangecontrib.infrared.widgets.owhyper.OWHyper"] settings_version = 3 settingsHandler = DomainContextHandler() imageplot = SettingProvider(ImagePlot) curveplot = SettingProvider(CurvePlotHyper) integration_method = Setting(0) integration_methods = Integrate.INTEGRALS value_type = Setting(0) attr_value = ContextSetting(None) lowlim = Setting(None) highlim = Setting(None) choose = Setting(None) graph_name = "imageplot.plotview" # defined so that the save button is shown class Warning(OWWidget.Warning): threshold_error = Msg("Low slider should be less than High") class Error(OWWidget.Warning): image_too_big = Msg("Image for chosen features is too big ({} x {}).") @classmethod def migrate_settings(cls, settings_, version): if version < 2: # delete the saved attr_value to prevent crashes try: del settings_["context_settings"][0].values["attr_value"] except: pass # migrate selection if version <= 2: try: current_context = settings_["context_settings"][0] selection = getattr(current_context, "selection", None) if selection is not None: selection = [(i, 1) for i in np.flatnonzero(np.array(selection))] settings_.setdefault("imageplot", {})["selection_group_saved"] = selection except: pass def __init__(self): super().__init__() dbox = gui.widgetBox(self.controlArea, "Image values") rbox = gui.radioButtons( dbox, self, "value_type", callback=self._change_integration) gui.appendRadioButton(rbox, "From spectra") self.box_values_spectra = gui.indentedBox(rbox) gui.comboBox( self.box_values_spectra, self, "integration_method", valueType=int, items=(a.name for a in self.integration_methods), callback=self._change_integral_type) gui.rubber(self.controlArea) gui.appendRadioButton(rbox, "Use feature") self.box_values_feature = gui.indentedBox(rbox) self.feature_value_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.feature_value = gui.comboBox( self.box_values_feature, self, "attr_value", callback=self.update_feature_value, model=self.feature_value_model, sendSelectedValue=True, valueType=str) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.imageplot = ImagePlot(self) self.imageplot.selection_changed.connect(self.output_image_selection) self.curveplot = CurvePlotHyper(self, select=SELECTONE) self.curveplot.selection_changed.connect(self.redraw_data) self.curveplot.plot.vb.x_padding = 0.005 # pad view so that lines are not hidden splitter.addWidget(self.imageplot) splitter.addWidget(self.curveplot) self.mainArea.layout().addWidget(splitter) self.line1 = MovableVline(position=self.lowlim, label="", report=self.curveplot) self.line1.sigMoved.connect(lambda v: setattr(self, "lowlim", v)) self.line2 = MovableVline(position=self.highlim, label="", report=self.curveplot) self.line2.sigMoved.connect(lambda v: setattr(self, "highlim", v)) self.line3 = MovableVline(position=self.choose, label="", report=self.curveplot) self.line3.sigMoved.connect(lambda v: setattr(self, "choose", v)) for line in [self.line1, self.line2, self.line3]: line.sigMoveFinished.connect(self.changed_integral_range) self.curveplot.add_marking(line) line.hide() self.data = None self.disable_integral_range = False self.resize(900, 700) self._update_integration_type() # prepare interface according to the new context self.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) def init_interface_data(self, data): same_domain = (self.data and data and data.domain == self.data.domain) if not same_domain: self.init_attr_values(data) def output_image_selection(self): if not self.data: self.Outputs.selected_data.send(None) self.Outputs.annotated_data.send(None) self.curveplot.set_data(None) return indices = np.flatnonzero(self.imageplot.selection_group) annotated_data = create_groups_table(self.data, self.imageplot.selection_group) if annotated_data is not None: annotated_data.X = self.data.X # workaround for Orange's copying on domain conversio self.Outputs.annotated_data.send(annotated_data) selected = self.data[indices] self.Outputs.selected_data.send(selected if selected else None) if selected: self.curveplot.set_data(selected) else: self.curveplot.set_data(self.data) def init_attr_values(self, data): domain = data.domain if data is not None else None self.feature_value_model.set_domain(domain) self.attr_value = self.feature_value_model[0] if self.feature_value_model else None def redraw_data(self): self.imageplot.update_view() def update_feature_value(self): self.redraw_data() def _update_integration_type(self): self.line1.hide() self.line2.hide() self.line3.hide() if self.value_type == 0: self.box_values_spectra.setDisabled(False) self.box_values_feature.setDisabled(True) if self.integration_methods[self.integration_method] != Integrate.PeakAt: self.line1.show() self.line2.show() else: self.line3.show() elif self.value_type == 1: self.box_values_spectra.setDisabled(True) self.box_values_feature.setDisabled(False) QTest.qWait(1) # first update the interface def _change_integration(self): # change what to show on the image self._update_integration_type() self.redraw_data() def changed_integral_range(self): if self.disable_integral_range: return self.redraw_data() def _change_integral_type(self): self._change_integration() @Inputs.data def set_data(self, data): self.closeContext() def valid_context(data): if data is None: return False annotation_features = [v for v in data.domain.metas + data.domain.class_vars if isinstance(v, (DiscreteVariable, ContinuousVariable))] return len(annotation_features) >= 1 if valid_context(data): self.openContext(data) else: # to generate valid interface even if context was not loaded self.contextAboutToBeOpened.emit([data]) self.data = data self.imageplot.set_data(data) self.curveplot.set_data(data) self._init_integral_boundaries() self.imageplot.update_view() self.output_image_selection() def _init_integral_boundaries(self): # requires data in curveplot self.disable_integral_range = True if self.curveplot.data_x is not None and len(self.curveplot.data_x): minx = self.curveplot.data_x[0] maxx = self.curveplot.data_x[-1] else: minx = 0. maxx = 1. if self.lowlim is None or not minx <= self.lowlim <= maxx: self.lowlim = minx self.line1.setValue(self.lowlim) if self.highlim is None or not minx <= self.highlim <= maxx: self.highlim = maxx self.line2.setValue(self.highlim) if self.choose is None: self.choose = (minx + maxx)/2 elif self.choose < minx: self.choose = minx elif self.choose > maxx: self.choose = maxx self.line3.setValue(self.choose) self.disable_integral_range = False def save_graph(self): # directly call save_graph so it hides axes self.imageplot.save_graph()
class OWHyper(OWWidget): name = "HyperSpectra" class Inputs: data = Input("Data", Orange.data.Table, default=True) class Outputs: selected_data = Output("Selection", Orange.data.Table, default=True) annotated_data = Output(ANNOTATED_DATA_SIGNAL_NAME, Orange.data.Table) icon = "icons/hyper.svg" priority = 20 replaces = ["orangecontrib.infrared.widgets.owhyper.OWHyper"] keywords = ["image", "spectral", "chemical", "imaging"] settings_version = 5 settingsHandler = DomainContextHandler() imageplot = SettingProvider(ImagePlot) curveplot = SettingProvider(CurvePlotHyper) integration_method = Setting(0) integration_methods = Integrate.INTEGRALS value_type = Setting(0) attr_value = ContextSetting(None) show_visible_image = Setting(False) visible_image_name = Setting(None) visible_image_composition = Setting('Normal') visible_image_opacity = Setting(120) lowlim = Setting(None) highlim = Setting(None) choose = Setting(None) graph_name = "imageplot.plotview" # defined so that the save button is shown class Warning(OWWidget.Warning): threshold_error = Msg("Low slider should be less than High") class Error(OWWidget.Error): image_too_big = Msg("Image for chosen features is too big ({} x {}).") class Information(OWWidget.Information): not_shown = Msg("Undefined positions: {} data point(s) are not shown.") @classmethod def migrate_settings(cls, settings_, version): if version < 2: # delete the saved attr_value to prevent crashes try: del settings_["context_settings"][0].values["attr_value"] except: # pylint: disable=bare-except pass # migrate selection if version <= 2: try: current_context = settings_["context_settings"][0] selection = getattr(current_context, "selection", None) if selection is not None: selection = [(i, 1) for i in np.flatnonzero(np.array(selection))] settings_.setdefault( "imageplot", {})["selection_group_saved"] = selection except: # pylint: disable=bare-except pass @classmethod def migrate_context(cls, context, version): if version <= 3 and "curveplot" in context.values: CurvePlot.migrate_context_sub_feature_color( context.values["curveplot"], version) def __init__(self): super().__init__() dbox = gui.widgetBox(self.controlArea, "Image values") rbox = gui.radioButtons(dbox, self, "value_type", callback=self._change_integration) gui.appendRadioButton(rbox, "From spectra") self.box_values_spectra = gui.indentedBox(rbox) gui.comboBox(self.box_values_spectra, self, "integration_method", items=(a.name for a in self.integration_methods), callback=self._change_integral_type) gui.rubber(self.controlArea) gui.appendRadioButton(rbox, "Use feature") self.box_values_feature = gui.indentedBox(rbox) self.feature_value_model = DomainModel( DomainModel.SEPARATED, valid_types=DomainModel.PRIMITIVE) self.feature_value = gui.comboBox(self.box_values_feature, self, "attr_value", contentsLength=12, searchable=True, callback=self.update_feature_value, model=self.feature_value_model) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.imageplot = ImagePlot(self) self.imageplot.selection_changed.connect(self.output_image_selection) # do not save visible image (a complex structure as a setting; # only save its name) self.visible_image = None self.setup_visible_image_controls() self.curveplot = CurvePlotHyper(self, select=SELECTONE) self.curveplot.selection_changed.connect(self.redraw_integral_info) self.curveplot.plot.vb.x_padding = 0.005 # pad view so that lines are not hidden splitter.addWidget(self.imageplot) splitter.addWidget(self.curveplot) self.mainArea.layout().addWidget(splitter) self.line1 = MovableVline(position=self.lowlim, label="", report=self.curveplot) self.line1.sigMoved.connect(lambda v: setattr(self, "lowlim", v)) self.line2 = MovableVline(position=self.highlim, label="", report=self.curveplot) self.line2.sigMoved.connect(lambda v: setattr(self, "highlim", v)) self.line3 = MovableVline(position=self.choose, label="", report=self.curveplot) self.line3.sigMoved.connect(lambda v: setattr(self, "choose", v)) for line in [self.line1, self.line2, self.line3]: line.sigMoveFinished.connect(self.changed_integral_range) self.curveplot.add_marking(line) line.hide() self.markings_integral = [] self.data = None self.disable_integral_range = False self.resize(900, 700) self._update_integration_type() # prepare interface according to the new context self.contextAboutToBeOpened.connect( lambda x: self.init_interface_data(x[0])) def setup_visible_image_controls(self): self.visbox = gui.widgetBox(self.controlArea, True) gui.checkBox(self.visbox, self, 'show_visible_image', label='Show visible image', callback=lambda: (self.update_visible_image_interface(), self.update_visible_image())) self.visible_image_model = VisibleImageListModel() gui.comboBox(self.visbox, self, 'visible_image', model=self.visible_image_model, callback=self.update_visible_image) self.visual_image_composition_modes = OrderedDict([ ('Normal', QPainter.CompositionMode_Source), ('Overlay', QPainter.CompositionMode_Overlay), ('Multiply', QPainter.CompositionMode_Multiply), ('Difference', QPainter.CompositionMode_Difference) ]) gui.comboBox(self.visbox, self, 'visible_image_composition', label='Composition mode:', model=PyListModel( self.visual_image_composition_modes.keys()), callback=self.update_visible_image_composition_mode) gui.hSlider(self.visbox, self, 'visible_image_opacity', label='Opacity:', minValue=0, maxValue=255, step=10, createLabel=False, callback=self.update_visible_image_opacity) self.update_visible_image_interface() self.update_visible_image_composition_mode() self.update_visible_image_opacity() def update_visible_image_interface(self): controlled = [ 'visible_image', 'visible_image_composition', 'visible_image_opacity' ] for c in controlled: getattr(self.controls, c).setEnabled(self.show_visible_image) def update_visible_image_composition_mode(self): self.imageplot.set_visible_image_comp_mode( self.visual_image_composition_modes[ self.visible_image_composition]) def update_visible_image_opacity(self): self.imageplot.set_visible_image_opacity(self.visible_image_opacity) def init_interface_data(self, data): same_domain = (self.data and data and data.domain == self.data.domain) if not same_domain: self.init_attr_values(data) self.init_visible_images(data) def output_image_selection(self): if not self.data: self.Outputs.selected_data.send(None) self.Outputs.annotated_data.send(None) self.curveplot.set_data(None) return indices = np.flatnonzero(self.imageplot.selection_group) annotated_data = groups_or_annotated_table( self.data, self.imageplot.selection_group) self.Outputs.annotated_data.send(annotated_data) selected = self.data[indices] self.Outputs.selected_data.send(selected if selected else None) if selected: self.curveplot.set_data(selected) else: self.curveplot.set_data(self.data) def init_attr_values(self, data): domain = data.domain if data is not None else None self.feature_value_model.set_domain(domain) self.attr_value = self.feature_value_model[ 0] if self.feature_value_model else None def init_visible_images(self, data): self.visible_image_model.clear() if data is not None and 'visible_images' in data.attributes: self.visbox.setEnabled(True) for img in data.attributes['visible_images']: self.visible_image_model.append(img) else: self.visbox.setEnabled(False) self.show_visible_image = False self.update_visible_image_interface() self._choose_visible_image() self.update_visible_image() def _choose_visible_image(self): # choose an image according to visible_image_name setting if len(self.visible_image_model): for img in self.visible_image_model: if img["name"] == self.visible_image_name: self.visible_image = img break else: self.visible_image = self.visible_image_model[0] def redraw_integral_info(self): di = {} integrate = self.image_values() if isinstance(integrate, Integrate) and np.any( self.curveplot.selection_group): # curveplot can have a subset of curves on the input> match IDs ind = np.flatnonzero(self.curveplot.selection_group)[0] dind = self.imageplot.data_ids[self.curveplot.data[ind].id] dshow = self.data[dind:dind + 1] datai = integrate(dshow) draw_info = datai.domain.attributes[0].compute_value.draw_info di = draw_info(dshow) self.refresh_markings(di) def refresh_markings(self, di): refresh_integral_markings([{ "draw": di }], self.markings_integral, self.curveplot) def image_values(self): if self.value_type == 0: # integrals imethod = self.integration_methods[self.integration_method] if imethod != Integrate.PeakAt: return Integrate(methods=imethod, limits=[[self.lowlim, self.highlim]]) else: return Integrate(methods=imethod, limits=[[self.choose, self.choose]]) else: return lambda data, attr=self.attr_value: \ data.transform(Domain([data.domain[attr]])) def image_values_fixed_levels(self): if self.value_type == 1 and isinstance(self.attr_value, DiscreteVariable): return 0, len(self.attr_value.values) - 1 return None def redraw_data(self): self.redraw_integral_info() self.imageplot.update_view() def update_feature_value(self): self.redraw_data() def _update_integration_type(self): self.line1.hide() self.line2.hide() self.line3.hide() if self.value_type == 0: self.box_values_spectra.setDisabled(False) self.box_values_feature.setDisabled(True) if self.integration_methods[ self.integration_method] != Integrate.PeakAt: self.line1.show() self.line2.show() else: self.line3.show() elif self.value_type == 1: self.box_values_spectra.setDisabled(True) self.box_values_feature.setDisabled(False) QTest.qWait(1) # first update the interface def _change_integration(self): # change what to show on the image self._update_integration_type() self.redraw_data() def changed_integral_range(self): if self.disable_integral_range: return self.redraw_data() def _change_integral_type(self): self._change_integration() @Inputs.data def set_data(self, data): self.closeContext() def valid_context(data): if data is None: return False annotation_features = [ v for v in data.domain.metas + data.domain.class_vars if isinstance(v, (DiscreteVariable, ContinuousVariable)) ] return len(annotation_features) >= 1 if valid_context(data): self.openContext(data) else: # to generate valid interface even if context was not loaded self.contextAboutToBeOpened.emit([data]) self.data = data self.imageplot.set_data(data) self.curveplot.set_data(data) self._init_integral_boundaries() self.imageplot.update_view() self.output_image_selection() self.update_visible_image() def _init_integral_boundaries(self): # requires data in curveplot self.disable_integral_range = True if self.curveplot.data_x is not None and len(self.curveplot.data_x): minx = self.curveplot.data_x[0] maxx = self.curveplot.data_x[-1] else: minx = 0. maxx = 1. if self.lowlim is None or not minx <= self.lowlim <= maxx: self.lowlim = minx self.line1.setValue(self.lowlim) if self.highlim is None or not minx <= self.highlim <= maxx: self.highlim = maxx self.line2.setValue(self.highlim) if self.choose is None: self.choose = (minx + maxx) / 2 elif self.choose < minx: self.choose = minx elif self.choose > maxx: self.choose = maxx self.line3.setValue(self.choose) self.disable_integral_range = False def save_graph(self): self.imageplot.save_graph() def onDeleteWidget(self): self.curveplot.shutdown() self.imageplot.shutdown() super().onDeleteWidget() def update_visible_image(self): img_info = self.visible_image if self.show_visible_image and img_info is not None: self.visible_image_name = img_info[ "name"] # save visual image name img = Image.open(img_info['image_ref']).convert('RGBA') # image must be vertically flipped # https://github.com/pyqtgraph/pyqtgraph/issues/315#issuecomment-214042453 # Behavior may change at pyqtgraph 1.0 version img = np.array(img)[::-1] width = img_info['img_size_x'] if 'img_size_x' in img_info \ else img.shape[1] * img_info['pixel_size_x'] height = img_info['img_size_y'] if 'img_size_y' in img_info \ else img.shape[0] * img_info['pixel_size_y'] rect = QRectF(img_info['pos_x'], img_info['pos_y'], width, height) self.imageplot.set_visible_image(img, rect) self.imageplot.show_visible_image() else: self.imageplot.hide_visible_image()
def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QVBoxLayout() self.controlArea.setLayout(layout) self.__method = Normalize.Vector self.lower = 0 self.upper = 4000 self.int_method = 0 self.attrs = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=ContinuousVariable) self.attrform = QFormLayout() self.chosen_attr = None self.last_domain = None self.saved_attr = None self.attrcb = gui.comboBox(None, self, "chosen_attr", callback=self.edited.emit, model=self.attrs) self.attrform.addRow("Normalize to", self.attrcb) self.areaform = QFormLayout() self.int_method_cb = QComboBox(enabled=False) self.int_method_cb.addItems(IntegrateEditor.Integrators) minf, maxf = -sys.float_info.max, sys.float_info.max self.lspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.lower, enabled=False) self.uspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.upper, enabled=False) self.areaform.addRow("Normalize to", self.int_method_cb) self.areaform.addRow("Lower limit", self.lspin) self.areaform.addRow("Upper limit", self.uspin) self._group = group = QButtonGroup(self) for name, method in self.Normalizers: rb = QRadioButton(self, text=name, checked=self.__method == method) layout.addWidget(rb) if method is Normalize.Attribute: layout.addLayout(self.attrform) elif method is Normalize.Area: layout.addLayout(self.areaform) group.addButton(rb, method) group.buttonClicked.connect(self.__on_buttonClicked) self.lspin.focusIn = self.activateOptions self.uspin.focusIn = self.activateOptions self.focusIn = self.activateOptions self.lspin.valueChanged[float].connect(self.setL) self.lspin.editingFinished.connect(self.reorderLimits) self.uspin.valueChanged[float].connect(self.setU) self.uspin.editingFinished.connect(self.reorderLimits) self.int_method_cb.currentIndexChanged.connect(self.setinttype) self.int_method_cb.activated.connect(self.edited) self.lline = MovableVline(position=self.lower, label="Low limit") self.lline.sigMoved.connect(self.setL) self.lline.sigMoveFinished.connect(self.reorderLimits) self.uline = MovableVline(position=self.upper, label="High limit") self.uline.sigMoved.connect(self.setU) self.uline.sigMoveFinished.connect(self.reorderLimits) self.user_changed = False
class NormalizeEditor(BaseEditorOrange): """ Normalize spectra. """ # Normalization methods Normalizers = [ ("Vector Normalization", Normalize.Vector), ("Min-Max Normalization", Normalize.MinMax), ("Area Normalization", Normalize.Area), ("Attribute Normalization", Normalize.Attribute), ("Standard Normal Variate (SNV)", Normalize.SNV), ("Normalize by Reference", NORMALIZE_BY_REFERENCE), ("Normalize by Reference (Complex Phase)", PHASE_REFERENCE)] def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QVBoxLayout() self.controlArea.setLayout(layout) self.__method = Normalize.Vector self.lower = 0 self.upper = 4000 self.int_method = 0 self.attrs = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=ContinuousVariable) self.attrform = QFormLayout() self.chosen_attr = None self.last_domain = None self.saved_attr = None self.attrcb = gui.comboBox(None, self, "chosen_attr", callback=self.edited.emit, model=self.attrs) self.attrform.addRow("Normalize to", self.attrcb) self.areaform = QFormLayout() self.int_method_cb = QComboBox(enabled=False) self.int_method_cb.addItems(IntegrateEditor.Integrators) minf, maxf = -sys.float_info.max, sys.float_info.max self.lspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.lower, enabled=False) self.uspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.upper, enabled=False) self.areaform.addRow("Normalize to", self.int_method_cb) self.areaform.addRow("Lower limit", self.lspin) self.areaform.addRow("Upper limit", self.uspin) self._group = group = QButtonGroup(self) for name, method in self.Normalizers: rb = QRadioButton(self, text=name, checked=self.__method == method) layout.addWidget(rb) if method is Normalize.Attribute: layout.addLayout(self.attrform) elif method is Normalize.Area: layout.addLayout(self.areaform) group.addButton(rb, method) group.buttonClicked.connect(self.__on_buttonClicked) self.lspin.focusIn = self.activateOptions self.uspin.focusIn = self.activateOptions self.focusIn = self.activateOptions self.lspin.valueChanged[float].connect(self.setL) self.lspin.editingFinished.connect(self.reorderLimits) self.uspin.valueChanged[float].connect(self.setU) self.uspin.editingFinished.connect(self.reorderLimits) self.int_method_cb.currentIndexChanged.connect(self.setinttype) self.int_method_cb.activated.connect(self.edited) self.lline = MovableVline(position=self.lower, label="Low limit") self.lline.sigMoved.connect(self.setL) self.lline.sigMoveFinished.connect(self.reorderLimits) self.uline = MovableVline(position=self.upper, label="High limit") self.uline.sigMoved.connect(self.setU) self.uline.sigMoveFinished.connect(self.reorderLimits) self.user_changed = False def activateOptions(self): self.parent_widget.curveplot.clear_markings() if self.__method == Normalize.Area: if self.lline not in self.parent_widget.curveplot.markings: self.parent_widget.curveplot.add_marking(self.lline) if (self.uline not in self.parent_widget.curveplot.markings and IntegrateEditor.Integrators_classes[self.int_method] is not Integrate.PeakAt): self.parent_widget.curveplot.add_marking(self.uline) def setParameters(self, params): if params: #parameters were manually set somewhere else self.user_changed = True method = params.get("method", Normalize.Vector) lower = params.get("lower", 0) upper = params.get("upper", 4000) int_method = params.get("int_method", 0) if method not in [method for name, method in self.Normalizers]: # handle old worksheets method = Normalize.Vector self.setMethod(method) self.int_method_cb.setCurrentIndex(int_method) self.setL(lower, user=False) self.setU(upper, user=False) self.saved_attr = params.get("attr") # chosen_attr will be set when data are connected def parameters(self): return {"method": self.__method, "lower": self.lower, "upper": self.upper, "int_method": self.int_method, "attr": self.chosen_attr} def setMethod(self, method): if self.__method != method: self.__method = method b = self._group.button(method) b.setChecked(True) for widget in [self.attrcb, self.int_method_cb, self.lspin, self.uspin]: widget.setEnabled(False) if method is Normalize.Attribute: self.attrcb.setEnabled(True) elif method is Normalize.Area: self.int_method_cb.setEnabled(True) self.lspin.setEnabled(True) self.uspin.setEnabled(True) self.activateOptions() self.changed.emit() def setL(self, lower, user=True): if user: self.user_changed = True if self.lower != lower: self.lower = lower with blocked(self.lspin): self.lspin.setValue(lower) self.lline.setValue(lower) self.changed.emit() def setU(self, upper, user=True): if user: self.user_changed = True if self.upper != upper: self.upper = upper with blocked(self.uspin): self.uspin.setValue(upper) self.uline.setValue(upper) self.changed.emit() def reorderLimits(self): if (IntegrateEditor.Integrators_classes[self.int_method] is Integrate.PeakAt): self.upper = self.lower + 10 limits = [self.lower, self.upper] self.lower, self.upper = min(limits), max(limits) self.lspin.setValue(self.lower) self.uspin.setValue(self.upper) self.lline.setValue(self.lower) self.uline.setValue(self.upper) self.edited.emit() def setinttype(self): if self.int_method != self.int_method_cb.currentIndex(): self.int_method = self.int_method_cb.currentIndex() self.reorderLimits() self.activateOptions() self.changed.emit() def __on_buttonClicked(self): method = self._group.checkedId() if method != self.__method: self.setMethod(self._group.checkedId()) self.edited.emit() @staticmethod def createinstance(params): method = params.get("method", Normalize.Vector) lower = params.get("lower", 0) upper = params.get("upper", 4000) int_method_index = params.get("int_method", 0) int_method = IntegrateEditor.Integrators_classes[int_method_index] attr = params.get("attr", None) if method not in (NORMALIZE_BY_REFERENCE, PHASE_REFERENCE): return Normalize(method=method, lower=lower, upper=upper, int_method=int_method, attr=attr) else: # avoids circular imports reference = params.get(REFERENCE_DATA_PARAM, None) if method == PHASE_REFERENCE: return NormalizePhaseReference(reference=reference) return NormalizeReference(reference=reference) def set_preview_data(self, data): edited = False if not self.user_changed: x = getx(data) if len(x): self.setL(min(x)) self.setU(max(x)) edited = True if data is not None and data.domain != self.last_domain: self.last_domain = data.domain self.attrs.set_domain(data.domain) try: # try to load the feature self.chosen_attr = self.saved_attr except ValueError: # could not load the chosen attr self.chosen_attr = self.attrs[0] if self.attrs else None self.saved_attr = self.chosen_attr edited = True if edited: self.edited.emit()
class LimitsBox(QHBoxLayout): """ Box with two limits and optional selection lines Args: limits (list): List containing low and high limit set label (str) : Label widget delete (bool): Include self-deletion button """ valueChanged = Signal(list, QObject) editingFinished = Signal(QObject) deleted = Signal(QObject) def __init__(self, parent=None, **kwargs): limits = kwargs.pop('limits', None) label = kwargs.pop('label', None) delete = kwargs.pop('delete', True) super().__init__(parent, **kwargs) minf, maxf = -sys.float_info.max, sys.float_info.max if label: self.addWidget(QLabel(label)) self.lowlime = SetXDoubleSpinBox(minimum=minf, maximum=maxf, singleStep=0.5, value=limits[0], maximumWidth=75) self.highlime = SetXDoubleSpinBox(minimum=minf, maximum=maxf, singleStep=0.5, value=limits[1], maximumWidth=75) self.lowlime.setValue(limits[0]) self.highlime.setValue(limits[1]) self.addWidget(self.lowlime) self.addWidget(self.highlime) if delete: self.button = QPushButton( QApplication.style().standardIcon( QStyle.SP_DockWidgetCloseButton), "") self.addWidget(self.button) self.button.clicked.connect(self.selfDelete) self.lowlime.valueChanged[float].connect(self.limitChanged) self.highlime.valueChanged[float].connect(self.limitChanged) self.lowlime.editingFinished.connect(self.editFinished) self.highlime.editingFinished.connect(self.editFinished) self.lowlime.focusIn = self.focusInChild self.highlime.focusIn = self.focusInChild self.line1 = MovableVline(position=limits[0], label=label + " - Low") self.line1.sigMoved.connect(self.lineLimitChanged) self.line2 = MovableVline(position=limits[1], label=label + " - High") self.line2.sigMoved.connect(self.lineLimitChanged) self.line1.sigMoveFinished.connect(self.editFinished) self.line2.sigMoveFinished.connect(self.editFinished) def focusInEvent(self, *e): self.focusIn() return super().focusInEvent(*e) def focusInChild(self): self.focusIn() def limitChanged(self): newlimits = [self.lowlime.value(), self.highlime.value()] self.line1.setValue(newlimits[0]) self.line2.setValue(newlimits[1]) self.valueChanged.emit(newlimits, self) def lineLimitChanged(self): newlimits = [self.line1.rounded_value(), self.line2.rounded_value()] self.lowlime.setValue(newlimits[0]) self.highlime.setValue(newlimits[1]) self.limitChanged() def editFinished(self): self.editingFinished.emit(self) def selfDelete(self): self.deleted.emit(self) self.removeLayout() def removeLayout(self): while self.count(): self.takeAt(0).widget().setParent(None) self.setParent(None)
class OWHyper(OWWidget): name = "HyperSpectra" class Inputs: data = Input("Data", Orange.data.Table, default=True) class Outputs: selected_data = Output("Selection", Orange.data.Table, default=True) annotated_data = Output(ANNOTATED_DATA_SIGNAL_NAME, Orange.data.Table) icon = "icons/hyper.svg" priority = 20 replaces = ["orangecontrib.infrared.widgets.owhyper.OWHyper"] settings_version = 3 settingsHandler = DomainContextHandler() imageplot = SettingProvider(ImagePlot) curveplot = SettingProvider(CurvePlotHyper) integration_method = Setting(0) integration_methods = Integrate.INTEGRALS value_type = Setting(0) attr_value = ContextSetting(None) lowlim = Setting(None) highlim = Setting(None) choose = Setting(None) graph_name = "imageplot.plotview" # defined so that the save button is shown class Warning(OWWidget.Warning): threshold_error = Msg("Low slider should be less than High") class Error(OWWidget.Warning): image_too_big = Msg("Image for chosen features is too big ({} x {}).") @classmethod def migrate_settings(cls, settings_, version): if version < 2: # delete the saved attr_value to prevent crashes try: del settings_["context_settings"][0].values["attr_value"] except: pass # migrate selection if version <= 2: try: current_context = settings_["context_settings"][0] selection = getattr(current_context, "selection", None) if selection is not None: selection = [(i, 1) for i in np.flatnonzero(np.array(selection))] settings_.setdefault("imageplot", {})["selection_group_saved"] = selection except: pass def __init__(self): super().__init__() dbox = gui.widgetBox(self.controlArea, "Image values") rbox = gui.radioButtons( dbox, self, "value_type", callback=self._change_integration) gui.appendRadioButton(rbox, "From spectra") self.box_values_spectra = gui.indentedBox(rbox) gui.comboBox( self.box_values_spectra, self, "integration_method", valueType=int, items=(a.name for a in self.integration_methods), callback=self._change_integral_type) gui.rubber(self.controlArea) gui.appendRadioButton(rbox, "Use feature") self.box_values_feature = gui.indentedBox(rbox) self.feature_value_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.feature_value = gui.comboBox( self.box_values_feature, self, "attr_value", callback=self.update_feature_value, model=self.feature_value_model, sendSelectedValue=True, valueType=str) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.imageplot = ImagePlot(self) self.imageplot.selection_changed.connect(self.output_image_selection) self.curveplot = CurvePlotHyper(self, select=SELECTONE) self.curveplot.selection_changed.connect(self.redraw_data) self.curveplot.plot.vb.x_padding = 0.005 # pad view so that lines are not hidden splitter.addWidget(self.imageplot) splitter.addWidget(self.curveplot) self.mainArea.layout().addWidget(splitter) self.line1 = MovableVline(position=self.lowlim, label="", report=self.curveplot) self.line1.sigMoved.connect(lambda v: setattr(self, "lowlim", v)) self.line2 = MovableVline(position=self.highlim, label="", report=self.curveplot) self.line2.sigMoved.connect(lambda v: setattr(self, "highlim", v)) self.line3 = MovableVline(position=self.choose, label="", report=self.curveplot) self.line3.sigMoved.connect(lambda v: setattr(self, "choose", v)) for line in [self.line1, self.line2, self.line3]: line.sigMoveFinished.connect(self.changed_integral_range) self.curveplot.add_marking(line) line.hide() self.data = None self.disable_integral_range = False self.resize(900, 700) self._update_integration_type() # prepare interface according to the new context self.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) def init_interface_data(self, data): same_domain = (self.data and data and data.domain == self.data.domain) if not same_domain: self.init_attr_values(data) def output_image_selection(self): if not self.data: self.Outputs.selected_data.send(None) self.Outputs.annotated_data.send(None) self.curveplot.set_data(None) return indices = np.flatnonzero(self.imageplot.selection_group) annotated_data = groups_or_annotated_table(self.data, self.imageplot.selection_group) self.Outputs.annotated_data.send(annotated_data) selected = self.data[indices] self.Outputs.selected_data.send(selected if selected else None) if selected: self.curveplot.set_data(selected) else: self.curveplot.set_data(self.data) def init_attr_values(self, data): domain = data.domain if data is not None else None self.feature_value_model.set_domain(domain) self.attr_value = self.feature_value_model[0] if self.feature_value_model else None def redraw_data(self): self.imageplot.update_view() def update_feature_value(self): self.redraw_data() def _update_integration_type(self): self.line1.hide() self.line2.hide() self.line3.hide() if self.value_type == 0: self.box_values_spectra.setDisabled(False) self.box_values_feature.setDisabled(True) if self.integration_methods[self.integration_method] != Integrate.PeakAt: self.line1.show() self.line2.show() else: self.line3.show() elif self.value_type == 1: self.box_values_spectra.setDisabled(True) self.box_values_feature.setDisabled(False) QTest.qWait(1) # first update the interface def _change_integration(self): # change what to show on the image self._update_integration_type() self.redraw_data() def changed_integral_range(self): if self.disable_integral_range: return self.redraw_data() def _change_integral_type(self): self._change_integration() @Inputs.data def set_data(self, data): self.closeContext() def valid_context(data): if data is None: return False annotation_features = [v for v in data.domain.metas + data.domain.class_vars if isinstance(v, (DiscreteVariable, ContinuousVariable))] return len(annotation_features) >= 1 if valid_context(data): self.openContext(data) else: # to generate valid interface even if context was not loaded self.contextAboutToBeOpened.emit([data]) self.data = data self.imageplot.set_data(data) self.curveplot.set_data(data) self._init_integral_boundaries() self.imageplot.update_view() self.output_image_selection() def _init_integral_boundaries(self): # requires data in curveplot self.disable_integral_range = True if self.curveplot.data_x is not None and len(self.curveplot.data_x): minx = self.curveplot.data_x[0] maxx = self.curveplot.data_x[-1] else: minx = 0. maxx = 1. if self.lowlim is None or not minx <= self.lowlim <= maxx: self.lowlim = minx self.line1.setValue(self.lowlim) if self.highlim is None or not minx <= self.highlim <= maxx: self.highlim = maxx self.line2.setValue(self.highlim) if self.choose is None: self.choose = (minx + maxx)/2 elif self.choose < minx: self.choose = minx elif self.choose > maxx: self.choose = maxx self.line3.setValue(self.choose) self.disable_integral_range = False def save_graph(self): self.imageplot.save_graph()
class LimitsBox(QHBoxLayout): """ Box with two limits and optional selection lines Args: limits (list): List containing low and high limit set label (str) : Label widget delete (bool): Include self-deletion button """ valueChanged = Signal(list, QObject) editingFinished = Signal(QObject) deleted = Signal(QObject) def __init__(self, parent=None, **kwargs): limits = kwargs.pop('limits', None) label = kwargs.pop('label', None) delete = kwargs.pop('delete', True) super().__init__(parent, **kwargs) minf, maxf = -sys.float_info.max, sys.float_info.max if label: self.addWidget(QLabel(label)) self.lowlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[0], maximumWidth=75) self.highlime = SetXDoubleSpinBox(decimals=2, minimum=minf, maximum=maxf, singleStep=0.5, value=limits[1], maximumWidth=75) self.lowlime.setValue(limits[0]) self.highlime.setValue(limits[1]) self.addWidget(self.lowlime) self.addWidget(self.highlime) if delete: self.button = QPushButton( QApplication.style().standardIcon(QStyle.SP_DockWidgetCloseButton), "") self.addWidget(self.button) self.button.clicked.connect(self.selfDelete) self.lowlime.valueChanged[float].connect(self.limitChanged) self.highlime.valueChanged[float].connect(self.limitChanged) self.lowlime.editingFinished.connect(self.editFinished) self.highlime.editingFinished.connect(self.editFinished) self.lowlime.focusIn = self.focusInChild self.highlime.focusIn = self.focusInChild self.line1 = MovableVline(position=limits[0], label=label + " - Low") self.line1.sigMoved.connect(self.lineLimitChanged) self.line2 = MovableVline(position=limits[1], label=label + " - High") self.line2.sigMoved.connect(self.lineLimitChanged) self.line1.sigMoveFinished.connect(self.editFinished) self.line2.sigMoveFinished.connect(self.editFinished) def focusInEvent(self, *e): self.focusIn() return super().focusInEvent(*e) def focusInChild(self): self.focusIn() def limitChanged(self): newlimits = [self.lowlime.value(), self.highlime.value()] self.line1.setValue(newlimits[0]) self.line2.setValue(newlimits[1]) self.valueChanged.emit(newlimits, self) def lineLimitChanged(self): newlimits = [self.line1.value(), self.line2.value()] self.lowlime.setValue(newlimits[0]) self.highlime.setValue(newlimits[1]) self.limitChanged() def editFinished(self): self.editingFinished.emit(self) def selfDelete(self): self.deleted.emit(self) self.removeLayout() def removeLayout(self): while self.count(): self.takeAt(0).widget().setParent(None) self.setParent(None)
class NormalizeEditor(BaseEditorOrange): """ Normalize spectra. """ # Normalization methods Normalizers = [ ("Vector Normalization", Normalize.Vector), ("Area Normalization", Normalize.Area), ("Attribute Normalization", Normalize.Attribute), ("Normalize by Reference", NORMALIZE_BY_REFERENCE)] def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) layout = QVBoxLayout() self.controlArea.setLayout(layout) self.__method = Normalize.Vector self.lower = 0 self.upper = 4000 self.int_method = 0 self.attrs = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=ContinuousVariable) self.attrform = QFormLayout() self.chosen_attr = None self.last_domain = None self.saved_attr = None self.attrcb = gui.comboBox(None, self, "chosen_attr", callback=self.edited.emit, model=self.attrs) self.attrform.addRow("Normalize to", self.attrcb) self.areaform = QFormLayout() self.int_method_cb = QComboBox(enabled=False) self.int_method_cb.addItems(IntegrateEditor.Integrators) minf, maxf = -sys.float_info.max, sys.float_info.max self.lspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.lower, enabled=False) self.uspin = SetXDoubleSpinBox( minimum=minf, maximum=maxf, singleStep=0.5, value=self.upper, enabled=False) self.areaform.addRow("Normalize to", self.int_method_cb) self.areaform.addRow("Lower limit", self.lspin) self.areaform.addRow("Upper limit", self.uspin) self._group = group = QButtonGroup(self) for name, method in self.Normalizers: rb = QRadioButton(self, text=name, checked=self.__method == method) layout.addWidget(rb) if method is Normalize.Attribute: layout.addLayout(self.attrform) elif method is Normalize.Area: layout.addLayout(self.areaform) group.addButton(rb, method) group.buttonClicked.connect(self.__on_buttonClicked) self.lspin.focusIn = self.activateOptions self.uspin.focusIn = self.activateOptions self.focusIn = self.activateOptions self.lspin.valueChanged[float].connect(self.setL) self.lspin.editingFinished.connect(self.reorderLimits) self.uspin.valueChanged[float].connect(self.setU) self.uspin.editingFinished.connect(self.reorderLimits) self.int_method_cb.currentIndexChanged.connect(self.setinttype) self.int_method_cb.activated.connect(self.edited) self.lline = MovableVline(position=self.lower, label="Low limit") self.lline.sigMoved.connect(self.setL) self.lline.sigMoveFinished.connect(self.reorderLimits) self.uline = MovableVline(position=self.upper, label="High limit") self.uline.sigMoved.connect(self.setU) self.uline.sigMoveFinished.connect(self.reorderLimits) self.user_changed = False def activateOptions(self): self.parent_widget.curveplot.clear_markings() if self.__method == Normalize.Area: if self.lline not in self.parent_widget.curveplot.markings: self.parent_widget.curveplot.add_marking(self.lline) if (self.uline not in self.parent_widget.curveplot.markings and IntegrateEditor.Integrators_classes[self.int_method] is not Integrate.PeakAt): self.parent_widget.curveplot.add_marking(self.uline) def setParameters(self, params): if params: #parameters were manually set somewhere else self.user_changed = True method = params.get("method", Normalize.Vector) lower = params.get("lower", 0) upper = params.get("upper", 4000) int_method = params.get("int_method", 0) if method not in [method for name, method in self.Normalizers]: # handle old worksheets method = Normalize.Vector self.setMethod(method) self.int_method_cb.setCurrentIndex(int_method) self.setL(lower, user=False) self.setU(upper, user=False) self.saved_attr = params.get("attr") # chosen_attr will be set when data are connected def parameters(self): return {"method": self.__method, "lower": self.lower, "upper": self.upper, "int_method": self.int_method, "attr": self.chosen_attr} def setMethod(self, method): if self.__method != method: self.__method = method b = self._group.button(method) b.setChecked(True) for widget in [self.attrcb, self.int_method_cb, self.lspin, self.uspin]: widget.setEnabled(False) if method is Normalize.Attribute: self.attrcb.setEnabled(True) elif method is Normalize.Area: self.int_method_cb.setEnabled(True) self.lspin.setEnabled(True) self.uspin.setEnabled(True) self.activateOptions() self.changed.emit() def setL(self, lower, user=True): if user: self.user_changed = True if self.lower != lower: self.lower = lower with blocked(self.lspin): self.lspin.setValue(lower) self.lline.setValue(lower) self.changed.emit() def setU(self, upper, user=True): if user: self.user_changed = True if self.upper != upper: self.upper = upper with blocked(self.uspin): self.uspin.setValue(upper) self.uline.setValue(upper) self.changed.emit() def reorderLimits(self): if (IntegrateEditor.Integrators_classes[self.int_method] is Integrate.PeakAt): self.upper = self.lower + 10 limits = [self.lower, self.upper] self.lower, self.upper = min(limits), max(limits) self.lspin.setValue(self.lower) self.uspin.setValue(self.upper) self.lline.setValue(self.lower) self.uline.setValue(self.upper) self.edited.emit() def setinttype(self): if self.int_method != self.int_method_cb.currentIndex(): self.int_method = self.int_method_cb.currentIndex() self.reorderLimits() self.activateOptions() self.changed.emit() def __on_buttonClicked(self): method = self._group.checkedId() if method != self.__method: self.setMethod(self._group.checkedId()) self.edited.emit() @staticmethod def createinstance(params): method = params.get("method", Normalize.Vector) lower = params.get("lower", 0) upper = params.get("upper", 4000) int_method_index = params.get("int_method", 0) int_method = IntegrateEditor.Integrators_classes[int_method_index] attr = params.get("attr", None) if method != NORMALIZE_BY_REFERENCE: return Normalize(method=method, lower=lower, upper=upper, int_method=int_method, attr=attr) else: # avoids circular imports from orangecontrib.spectroscopy.widgets.owpreprocess import REFERENCE_DATA_PARAM reference = params.get(REFERENCE_DATA_PARAM, None) return NormalizeReference(reference=reference) def set_preview_data(self, data): edited = False if not self.user_changed: x = getx(data) if len(x): self.setL(min(x)) self.setU(max(x)) edited = True if data is not None and data.domain != self.last_domain: self.last_domain = data.domain self.attrs.set_domain(data.domain) try: # try to load the feature self.chosen_attr = self.saved_attr except ValueError: # could not load the chosen attr self.chosen_attr = self.attrs[0] if self.attrs else None self.saved_attr = self.chosen_attr edited = True if edited: self.edited.emit()