def __init__(self, parent=None): super(LevelsHistogram, self).__init__(parent=parent, title="", section="histogram") self.antialiased = False # a dict of dict : plot -> selected items -> HistogramItem self._tracked_items = {} self.curveparam = CurveParam(_("Curve"), icon="curve.png") self.curveparam.read_config(CONF, "histogram", "curve") self.histparam = HistogramParam(_("Histogram"), icon="histogram.png") self.histparam.logscale = False self.histparam.n_bins = 256 self.range = XRangeSelection(0, 1) self.range_mono_color = self.range.shapeparam.sel_line.color self.range_multi_color = CONF.get("histogram", "range/multi/color", "red") self.add_item(self.range, z=5) self.SIG_RANGE_CHANGED.connect(self.range_changed) self.set_active_item(self.range) self.setMinimumHeight(80) self.setAxisMaxMajor(self.Y_LEFT, 5) self.setAxisMaxMinor(self.Y_LEFT, 0) if parent is None: self.set_axis_title("bottom", "Levels")
def __init__(self, parent=None): super(LevelsHistogram, self).__init__(parent=parent, title="", section="histogram") self.antialiased = False # a dict of dict : plot -> selected items -> HistogramItem self._tracked_items = {} self.curveparam = CurveParam(_("Curve"), icon="curve.png") self.curveparam.read_config(CONF, "histogram", "curve") self.histparam = HistogramParam(_("Histogram"), icon="histogram.png") self.histparam.logscale = False self.histparam.n_bins = 256 self.range = XRangeSelection(0, 1) self.range_mono_color = self.range.shapeparam.sel_line.color self.range_multi_color = CONF.get("histogram", "range/multi/color", "red") self.add_item(self.range, z=5) self.connect(self, SIG_RANGE_CHANGED, self.range_changed) self.set_active_item(self.range) self.setMinimumHeight(80) self.setAxisMaxMajor(self.Y_LEFT, 5) self.setAxisMaxMinor(self.Y_LEFT, 0) if parent is None: self.set_axis_title('bottom', 'Levels')
def __init__(self, min_, max_): XRangeSelection.__init__(self, min_, max_) self._can_move = False # moving entire shape disabled, but handles are still movable # we have to trick a bit because pyqtSignal must be attributes of a derived class of # QObject and adding QObject as an additional base class does not work somehow: self._x = SnappingRangeSelection._X() self.SELECTED_RANGE_CHANGED = self._x.SELECTED_RANGE_CHANGED p = self.shapeparam p.fill = "#aaaaaa" p.line.color = "#888888" p.sel_line.color = "#888888" p.symbol.color = "gray" p.symbol.facecolor = "gray" p.symbol.alpha = 0.5 p.sel_symbol.color = "gray" p.sel_symbol.facecolor = "gray" p.sel_symbol.alpha = 0.5 p.sel_symbol.size = 8 p.symbol.size = 8 p.update_range(self)
class LevelsHistogram(CurvePlot): """Image levels histogram widget""" #: Signal emitted by LevelsHistogram when LUT range was changed SIG_VOI_CHANGED = Signal() def __init__(self, parent=None): super(LevelsHistogram, self).__init__(parent=parent, title="", section="histogram") self.antialiased = False # a dict of dict : plot -> selected items -> HistogramItem self._tracked_items = {} self.curveparam = CurveParam(_("Curve"), icon="curve.png") self.curveparam.read_config(CONF, "histogram", "curve") self.histparam = HistogramParam(_("Histogram"), icon="histogram.png") self.histparam.logscale = False self.histparam.n_bins = 256 self.range = XRangeSelection(0, 1) self.range_mono_color = self.range.shapeparam.sel_line.color self.range_multi_color = CONF.get("histogram", "range/multi/color", "red") self.add_item(self.range, z=5) self.SIG_RANGE_CHANGED.connect(self.range_changed) self.set_active_item(self.range) self.setMinimumHeight(80) self.setAxisMaxMajor(self.Y_LEFT, 5) self.setAxisMaxMinor(self.Y_LEFT, 0) if parent is None: self.set_axis_title("bottom", "Levels") def connect_plot(self, plot): if not isinstance(plot, ImagePlot): # Connecting only to image plot widgets (allow mixing image and # curve widgets for the same plot manager -- e.g. in pyplot) return self.SIG_VOI_CHANGED.connect(plot.notify_colormap_changed) plot.SIG_ITEM_SELECTION_CHANGED.connect(self.selection_changed) plot.SIG_ITEM_REMOVED.connect(self.item_removed) plot.SIG_ACTIVE_ITEM_CHANGED.connect(self.active_item_changed) def tracked_items_gen(self): for plot, items in list(self._tracked_items.items()): for item in list(items.items()): yield item # tuple item,curve def __del_known_items(self, known_items, items): del_curves = [] for item in list(known_items.keys()): if item not in items: curve = known_items.pop(item) del_curves.append(curve) self.del_items(del_curves) def selection_changed(self, plot): items = plot.get_selected_items(item_type=IVoiImageItemType) known_items = self._tracked_items.setdefault(plot, {}) if items: self.__del_known_items(known_items, items) if len(items) == 1: # Removing any cached item for other plots for other_plot, _items in list(self._tracked_items.items()): if other_plot is not plot: if not other_plot.get_selected_items( item_type=IVoiImageItemType): other_known_items = self._tracked_items[other_plot] self.__del_known_items(other_known_items, []) else: # if all items are deselected we keep the last known # selection (for one plot only) for other_plot, _items in list(self._tracked_items.items()): if other_plot.get_selected_items(item_type=IVoiImageItemType): self.__del_known_items(known_items, []) break for item in items: if item not in known_items: curve = HistogramItem(self.curveparam, self.histparam) curve.set_hist_source(item) self.add_item(curve, z=0) known_items[item] = curve nb_selected = len(list(self.tracked_items_gen())) if not nb_selected: self.replot() return self.curveparam.shade = 1.0 / nb_selected for item, curve in self.tracked_items_gen(): self.curveparam.update_curve(curve) self.histparam.update_hist(curve) self.active_item_changed(plot) # Rescaling histogram plot axes for better visibility ymax = None for item in known_items: curve = known_items[item] _x, y = curve.get_data() ymax0 = y.mean() + 3 * y.std() if ymax is None or ymax0 > ymax: ymax = ymax0 ymin, _ymax = self.get_axis_limits("left") if ymax is not None: self.set_axis_limits("left", ymin, ymax) self.replot() def item_removed(self, item): for plot, items in list(self._tracked_items.items()): if item in items: curve = items.pop(item) self.del_items([curve]) self.replot() break def active_item_changed(self, plot): items = plot.get_selected_items(item_type=IVoiImageItemType) if not items: # XXX: workaround return active = plot.get_last_active_item(IVoiImageItemType) if active: active_range = active.get_lut_range() else: active_range = None multiple_ranges = False for item, curve in self.tracked_items_gen(): if active_range != item.get_lut_range(): multiple_ranges = True if active_range is not None: _m, _M = active_range self.set_range_style(multiple_ranges) self.range.set_range(_m, _M, dosignal=False) self.replot() def set_range_style(self, multiple_ranges): if multiple_ranges: self.range.shapeparam.sel_line.color = self.range_multi_color else: self.range.shapeparam.sel_line.color = self.range_mono_color self.range.shapeparam.update_range(self.range) def set_range(self, _min, _max): if _min < _max: self.set_range_style(False) self.range.set_range(_min, _max) self.replot() return True else: # Range was not changed return False def range_changed(self, _rangesel, _min, _max): for item, curve in self.tracked_items_gen(): item.set_lut_range([_min, _max]) self.SIG_VOI_CHANGED.emit() def set_full_range(self): """Set range bounds to image min/max levels""" _min = _max = None for item, curve in self.tracked_items_gen(): imin, imax = item.get_lut_range_full() if _min is None or _min > imin: _min = imin if _max is None or _max < imax: _max = imax if _min is not None: self.set_range(_min, _max) def apply_min_func(self, item, curve, min): _min, _max = item.get_lut_range() return min, _max def apply_max_func(self, item, curve, max): _min, _max = item.get_lut_range() return _min, max def reduce_range_func(self, item, curve, percent): return lut_range_threshold(item, curve.bins, percent) def apply_range_function(self, func, *args, **kwargs): item = None for item, curve in self.tracked_items_gen(): _min, _max = func(item, curve, *args, **kwargs) item.set_lut_range([_min, _max]) self.SIG_VOI_CHANGED.emit() if item is not None: self.active_item_changed(item.plot()) def eliminate_outliers(self, percent): """ Eliminate outliers: eliminate percent/2*N counts on each side of the histogram (where N is the total count number) """ self.apply_range_function(self.reduce_range_func, percent) def set_min(self, _min): self.apply_range_function(self.apply_min_func, _min) def set_max(self, _max): self.apply_range_function(self.apply_max_func, _max)
class LevelsHistogram(CurvePlot): """Image levels histogram widget""" def __init__(self, parent=None): super(LevelsHistogram, self).__init__(parent=parent, title="", section="histogram") self.antialiased = False # a dict of dict : plot -> selected items -> HistogramItem self._tracked_items = {} self.curveparam = CurveParam(_("Curve"), icon="curve.png") self.curveparam.read_config(CONF, "histogram", "curve") self.histparam = HistogramParam(_("Histogram"), icon="histogram.png") self.histparam.logscale = False self.histparam.n_bins = 256 self.range = XRangeSelection(0, 1) self.range_mono_color = self.range.shapeparam.sel_line.color self.range_multi_color = CONF.get("histogram", "range/multi/color", "red") self.add_item(self.range, z=5) self.connect(self, SIG_RANGE_CHANGED, self.range_changed) self.set_active_item(self.range) self.setMinimumHeight(80) self.setAxisMaxMajor(self.Y_LEFT, 5) self.setAxisMaxMinor(self.Y_LEFT, 0) if parent is None: self.set_axis_title('bottom', 'Levels') def connect_plot(self, plot): if not isinstance(plot, ImagePlot): # Connecting only to image plot widgets (allow mixing image and # curve widgets for the same plot manager -- e.g. in pyplot) return self.connect(self, SIG_VOI_CHANGED, plot.notify_colormap_changed) self.connect(plot, SIG_ITEM_SELECTION_CHANGED, self.selection_changed) self.connect(plot, SIG_ITEM_REMOVED, self.item_removed) self.connect(plot, SIG_ACTIVE_ITEM_CHANGED, self.active_item_changed) def tracked_items_gen(self): for plot, items in list(self._tracked_items.items()): for item in list(items.items()): yield item # tuple item,curve def __del_known_items(self, known_items, items): del_curves = [] for item in list(known_items.keys()): if item not in items: curve = known_items.pop(item) del_curves.append(curve) self.del_items(del_curves) def selection_changed(self, plot): items = plot.get_selected_items(item_type=IVoiImageItemType) known_items = self._tracked_items.setdefault(plot, {}) if items: self.__del_known_items(known_items, items) if len(items) == 1: # Removing any cached item for other plots for other_plot, _items in list(self._tracked_items.items()): if other_plot is not plot: if not other_plot.get_selected_items( item_type=IVoiImageItemType): other_known_items = self._tracked_items[other_plot] self.__del_known_items(other_known_items, []) else: # if all items are deselected we keep the last known # selection (for one plot only) for other_plot, _items in list(self._tracked_items.items()): if other_plot.get_selected_items(item_type=IVoiImageItemType): self.__del_known_items(known_items, []) break for item in items: if item not in known_items: curve = HistogramItem(self.curveparam, self.histparam) curve.set_hist_source(item) self.add_item(curve, z=0) known_items[item] = curve nb_selected = len(list(self.tracked_items_gen())) if not nb_selected: self.replot() return self.curveparam.shade = 1.0/nb_selected for item, curve in self.tracked_items_gen(): self.curveparam.update_curve(curve) self.histparam.update_hist(curve) self.active_item_changed(plot) # Rescaling histogram plot axes for better visibility ymax = None for item in known_items: curve = known_items[item] _x, y = curve.get_data() ymax0 = y.mean()+3*y.std() if ymax is None or ymax0 > ymax: ymax = ymax0 ymin, _ymax = self.get_axis_limits("left") if ymax is not None: self.set_axis_limits("left", ymin, ymax) self.replot() def item_removed(self, item): for plot, items in list(self._tracked_items.items()): if item in items: items.pop(item) break def active_item_changed(self, plot): items = plot.get_selected_items(item_type=IVoiImageItemType) if not items: #XXX: workaround return active = plot.get_last_active_item(IVoiImageItemType) if active: active_range = active.get_lut_range() else: active_range = None multiple_ranges = False for item, curve in self.tracked_items_gen(): if active_range != item.get_lut_range(): multiple_ranges = True if active_range is not None: _m, _M = active_range self.set_range_style(multiple_ranges) self.range.set_range(_m, _M, dosignal=False) self.replot() def set_range_style(self, multiple_ranges): if multiple_ranges: self.range.shapeparam.sel_line.color = self.range_multi_color else: self.range.shapeparam.sel_line.color = self.range_mono_color self.range.shapeparam.update_range(self.range) def set_range(self, _min, _max): if _min < _max: self.set_range_style(False) self.range.set_range(_min, _max) self.replot() return True else: # Range was not changed return False def range_changed(self, _rangesel, _min, _max): for item, curve in self.tracked_items_gen(): item.set_lut_range([_min, _max]) self.emit(SIG_VOI_CHANGED) def set_full_range(self): """Set range bounds to image min/max levels""" _min = _max = None for item, curve in self.tracked_items_gen(): imin, imax = item.get_lut_range_full() if _min is None or _min>imin: _min = imin if _max is None or _max<imax: _max = imax if _min is not None: self.set_range(_min, _max) def apply_min_func(self, item, curve, min): _min, _max = item.get_lut_range() return min, _max def apply_max_func(self, item, curve, max): _min, _max = item.get_lut_range() return _min, max def reduce_range_func(self, item, curve, percent): return lut_range_threshold(item, curve.bins, percent) def apply_range_function(self, func, *args, **kwargs): item = None for item, curve in self.tracked_items_gen(): _min, _max = func(item, curve, *args, **kwargs) item.set_lut_range([_min, _max]) self.emit(SIG_VOI_CHANGED) if item is not None: self.active_item_changed(item.plot()) def eliminate_outliers(self, percent): """ Eliminate outliers: eliminate percent/2*N counts on each side of the histogram (where N is the total count number) """ self.apply_range_function(self.reduce_range_func, percent) def set_min(self, _min): self.apply_range_function(self.apply_min_func, _min) def set_max(self, _max): self.apply_range_function(self.apply_max_func, _max)
def range(self, xmin, xmax): return XRangeSelection(xmin, xmax)
def create_shape(self): return XRangeSelection(0, 0)
def create_shape(self): self.label = None return XRangeSelection(0, 0)
def create_shape(self): from guiqwt.shapes import XRangeSelection return XRangeSelection(0, 0)