Skip to content

Commit

Permalink
Merge pull request #930 from psavery/bc-set-data-range
Browse files Browse the repository at this point in the history
Add ability to set data range in B&C editor
  • Loading branch information
joelvbernier authored May 13, 2021
2 parents ea9c56e + 63ecce7 commit cdfe3a2
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 57 deletions.
94 changes: 75 additions & 19 deletions hexrd/ui/brightness_contrast_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
from scipy.interpolate import interp1d

from PySide2.QtCore import QObject, Signal
from PySide2.QtWidgets import (
QDialog, QDialogButtonBox, QMessageBox, QVBoxLayout
)

from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure

from hexrd.ui.range_widget import RangeWidget
from hexrd.ui.ui_loader import UiLoader
from hexrd.ui.utils import block_signals, reversed_enumerate

Expand All @@ -28,6 +32,8 @@ def __init__(self, parent=None):
self._ui_min, self._ui_max = self._data_range
self._data = None
self.histogram = None
self.histogram_artist = None
self.line_artist = None

self.default_auto_threshold = 5000
self.current_auto_threshold = self.default_auto_threshold
Expand All @@ -36,7 +42,6 @@ def __init__(self, parent=None):
self.ui = loader.load_file('brightness_contrast_editor.ui', parent)

self.setup_plot()
self.setup_line()

self.ui.minimum.setMaximum(NUM_INCREMENTS)
self.ui.maximum.setMaximum(NUM_INCREMENTS)
Expand All @@ -51,6 +56,7 @@ def setup_connections(self):
self.ui.brightness.valueChanged.connect(self.brightness_edited)
self.ui.contrast.valueChanged.connect(self.contrast_edited)

self.ui.set_data_range.pressed.connect(self.select_data_range)
self.ui.reset.pressed.connect(self.reset_pressed)
self.ui.auto_button.pressed.connect(self.auto_pressed)

Expand All @@ -61,6 +67,8 @@ def data_range(self):
@data_range.setter
def data_range(self, v):
self._data_range = v
self.clip_ui_range()
self.ensure_min_max_space('max')
self.update_gui()

@property
Expand All @@ -70,7 +78,7 @@ def data(self):
@data.setter
def data(self, v):
self._data = v
self.update_data_range()
self.reset_data_range()

@property
def data_list(self):
Expand All @@ -83,15 +91,18 @@ def data_list(self):
else:
return [self.data]

def update_data_range(self):
@property
def data_bounds(self):
if self.data is None:
self.data_range = (0, 1)
return
return (0, 1)

data = self.data_list
mins = [x.min() for x in data]
maxes = [x.max() for x in data]
self.data_range = (min(mins), max(maxes))
return (min(mins), max(maxes))

def reset_data_range(self):
self.data_range = self.data_bounds

def update_gui(self):
self.update_brightness()
Expand Down Expand Up @@ -289,7 +300,15 @@ def setup_plot(self):

self.ui.plot_layout.addWidget(self.canvas)

def clear_plot(self):
self.axis.clear()
self.histogram_artist = None
self.line_artist = None

def update_histogram(self):
# Clear the plot so everything will be re-drawn from scratch
self.clear_plot()

data = self.data_list
if not data:
return
Expand All @@ -310,16 +329,17 @@ def update_histogram(self):
'bins': HISTOGRAM_NUM_BINS,
'color': 'black',
}
self.axis.hist(**kwargs)
self.canvas.draw_idle()
self.histogram_artist = self.axis.hist(**kwargs)[2]

self.canvas.draw()

def update_range_labels(self):
labels = (self.ui.min_label, self.ui.max_label)
texts = [f'{x:.2f}' for x in self.ui_range]
for label, text in zip(labels, texts):
label.setText(text)

def setup_line(self):
def create_line(self):
xs = (self.ui_min, self.ui_max)
ys = self.axis.get_ylim()
kwargs = {
Expand All @@ -330,6 +350,9 @@ def setup_line(self):
self.line_artist, = self.axis.plot(xs, ys, **kwargs)

def update_line(self):
if self.line_artist is None:
self.create_line()

xs = (self.ui_min, self.ui_max)
ys = self.axis.get_ylim()

Expand All @@ -341,14 +364,46 @@ def update_line(self):
self.line_artist.set_data(interp(xs), ys)
self.canvas.draw_idle()

def clear_plot(self):
self.figure.clear()

@property
def max_num_pixels(self):
return max(np.prod(x.shape) for x in self.data_list)

def select_data_range(self):
dialog = QDialog(self.ui)
layout = QVBoxLayout()
dialog.setLayout(layout)

range_widget = RangeWidget(dialog)
range_widget.bounds = self.data_bounds
range_widget.min = self.data_range[0]
range_widget.max = self.data_range[1]
layout.addWidget(range_widget.ui)

buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
button_box = QDialogButtonBox(buttons, dialog)
button_box.accepted.connect(dialog.accept)
button_box.rejected.connect(dialog.reject)
layout.addWidget(button_box)

if not dialog.exec_():
# User canceled
return

data_range = range_widget.range
if data_range[0] >= data_range[1]:
message = 'Min cannot be greater than or equal to the max'
QMessageBox.critical(self.ui, 'Validation Error', message)
return

if self.data_range == data_range:
# Nothing changed...
return

self.data_range = data_range
self.modified()

def reset_pressed(self):
self.reset_data_range()
self.reset_auto_threshold()
self.reset.emit()

Expand Down Expand Up @@ -393,14 +448,15 @@ def auto_pressed(self):

if h_max < h_min:
# Reset the range
self.reset_pressed()
return
self.reset_auto_threshold()
self.ui_range = self.data_range
else:
vmin = hist_start + h_min * bin_size
vmax = hist_start + h_max * bin_size
if vmin == vmax:
vmin, vmax = data_range

vmin = hist_start + h_min * bin_size
vmax = hist_start + h_max * bin_size
if vmin == vmax:
vmin, vmax = data_range
self.ui_range = vmin, vmax

self.ui_range = vmin, vmax
self.update_brightness()
self.update_contrast()
3 changes: 3 additions & 0 deletions hexrd/ui/color_map_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ def update_bc_enable_state(self):
self.ui.bc_editor_button.setEnabled(has_data)

def bc_editor_button_pressed(self):
if self.bc_editor:
self.bc_editor.ui.reject()

bc = self.bc_editor = BrightnessContrastEditor(self.ui)
bc.data = self.data
bc.edited.connect(self.bc_editor_modified)
Expand Down
40 changes: 40 additions & 0 deletions hexrd/ui/range_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from hexrd.ui.ui_loader import UiLoader


class RangeWidget:

def __init__(self, parent=None):
loader = UiLoader()
self.ui = loader.load_file('range_widget.ui', parent)

@property
def min(self):
return self.ui.min.value()

@min.setter
def min(self, v):
self.ui.min.setValue(v)

@property
def max(self):
return self.ui.max.value()

@max.setter
def max(self, v):
self.ui.max.setValue(v)

@property
def range(self):
return (self.min, self.max)

@property
def bounds(self):
return (self.ui.min.minimum(), self.ui.max.maximum())

@bounds.setter
def bounds(self, v):
self.ui.min.setMinimum(v[0])
self.ui.max.setMaximum(v[1])

self.ui.min.setToolTip(f'Min: {v[0]}')
self.ui.max.setToolTip(f'Max: {v[1]}')
Loading

0 comments on commit cdfe3a2

Please sign in to comment.