Skip to content

Commit

Permalink
Added doc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Neverhorst committed Apr 11, 2019
1 parent d30e92a commit 063d9c7
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
20 changes: 20 additions & 0 deletions core/util/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@


def scan_blink_correction(image, axis=1):
"""
This filter can be used to filter out impulsive noise from a 2D array along a single axis.
As filter we apply a sequence of two filters. First a min-filter and then a max-filter.
This composite non-linear filter technique is also called opening filter.
This filter will completely remove single-pixel (along given axis) brightness spikes from the
image but will cause the image to be more "blocky"/less smooth.
Of course you need to ensure that the image features of interest are larger than
@param numpy.ndarray image: A 2D numpy array to be filtered (e.g. image data)
@param int axis: The axis along which to apply the 1D filter
@return numpy.ndarray: The filtered image. Same dimensions as input image
"""

if not isinstance(image, np.ndarray):
logger.error('Image must be 2D numpy array.')
return image
Expand All @@ -37,8 +51,14 @@ def scan_blink_correction(image, axis=1):
logger.error('Optional axis parameter must be either 0 or 1.')
return image

# Calculate median value of the image. This value is used for padding image boundaries during
# filtering.
median = np.median(image)
# Apply a minimum filter along the chosen axis.
filt_img = minimum_filter1d(image, size=2, axis=axis, mode='constant', cval=median)
# Apply a maximum filter along the chosen axis. Flip the previous filter result to avoid
# translation of image features.
filt_img = maximum_filter1d(
np.flip(filt_img, axis), size=2, axis=axis, mode='constant', cval=median)
# Flip back the image to obtain original orientation and return result.
return np.flip(filt_img, axis)
63 changes: 56 additions & 7 deletions qtwidgets/scan_plotwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class ScanImageItem(ImageItem):
Adds the signal sigMouseClicked to tap into mouse click events and receive the real world data
coordinate of the click.
Adds blink correction functionality capable of filtering out single pixel wide artifacts along
a single image dimension.
a single image dimension. This is done by applying a non-linear 1D min-max-filter along a
single image dimension.
"""
sigMouseClicked = QtCore.Signal(object, QtCore.QPointF)

Expand Down Expand Up @@ -96,10 +97,13 @@ def mouseClickEvent(self, ev):
class ScanPlotWidget(PlotWidget):
"""
Extend the PlotWidget Class with more functionality used for qudi scan images.
Supported features:
- draggable/static crosshair with optional range and size constraints.
- zoom feature by rubberband selection
- rubberband area selection
This class can be promoted in the Qt designer. Here you can predefine or
redefined all methods and class variables, which should be used in the
Qt Designer before it will be loaded into the created ui file.
This class depends on the ScanViewBox class defined further below.
This class can be promoted in the Qt designer.
"""
sigMouseAreaSelected = QtCore.Signal(QtCore.QRectF) # mapped rectangle mouse cursor selection
sigCrosshairPosChanged = QtCore.Signal(QtCore.QPointF)
Expand Down Expand Up @@ -191,6 +195,10 @@ def toggle_zoom_by_selection(self, enable):
return self.getViewBox().toggle_zoom_by_selection(enable)

def _update_pos_from_line(self, obj):
"""
Called each time the position of the InfiniteLines has been changed by a user drag.
Causes the crosshair rectangle to follow the lines.
"""
if obj not in (self.hline, self.vline):
return
pos = self.vline.pos()
Expand All @@ -203,6 +211,10 @@ def _update_pos_from_line(self, obj):
return

def _update_pos_from_roi(self, obj):
"""
Called each time the position of the rectangular ROI has been changed by a user drag.
Causes the InfiniteLines to follow the ROI.
"""
if obj is not self.crosshair:
return
pos = self.crosshair.pos()
Expand All @@ -216,9 +228,11 @@ def _update_pos_from_roi(self, obj):

def toggle_crosshair(self, enable, movable=True):
"""
Disable/Enable the crosshair within the PlotWidget. Optionally also toggle if it can be
dragged by the user.
@param bool enable:
@param bool movable:
@param bool enable: enable crosshair (True), disable crosshair (False)
@param bool movable: enable user drag (True), disable user drag (False)
"""
if not isinstance(enable, bool):
raise TypeError('Positional argument "enable" must be bool type.')
Expand All @@ -240,15 +254,21 @@ def toggle_crosshair(self, enable, movable=True):

def toggle_crosshair_movable(self, enable):
"""
Toggle if the crosshair can be dragged by the user.
@param enable:
@param bool enable: enable (True), disable (False)
"""
self.crosshair.translatable = bool(enable)
self.vline.setMovable(enable)
self.hline.setMovable(enable)
return

def set_crosshair_pos(self, pos):
"""
Set the crosshair center to the given coordinates.
@param QPointF|float[2] pos: (x,y) position of the crosshair
"""
try:
pos = tuple(pos)
except TypeError:
Expand All @@ -268,6 +288,14 @@ def set_crosshair_pos(self, pos):
return

def set_crosshair_size(self, size, force_default=True):
"""
Set the default size of the crosshair rectangle (x, y) and update the display.
@param QSize|float[2] size: the (x,y) size of the crosshair rectangle
@param bool force_default: Set default crosshair size and enforce minimal size (True).
Enforce displayed crosshair size while keeping default size
untouched (False).
"""
try:
size = tuple(size)
except TypeError:
Expand Down Expand Up @@ -298,6 +326,16 @@ def set_crosshair_size(self, size, force_default=True):
return

def set_crosshair_min_size_factor(self, factor):
"""
Sets the minimum crosshair size factor. This will determine the minimum size of the
smallest edge of the crosshair center rectangle.
This minimum size is calculated by taking the smallest visible axis of the ViewBox and
multiplying it with the scale factor set by this method.
The crosshair rectangle will be then scaled accordingly if the set crosshair size is
smaller than this minimal size.
@param float factor: The scale factor to set. If <= 0 no minimal crosshair size enforced.
"""
if factor <= 0:
self._min_crosshair_factor = 0
elif factor <= 1:
Expand All @@ -307,6 +345,12 @@ def set_crosshair_min_size_factor(self, factor):
return

def set_crosshair_range(self, new_range):
"""
Sets a range boundary for the crosshair position.
@param float[2][2] new_range: two min-max range value tuples (for x and y axis).
If None set unlimited ranges.
"""
if new_range is None:
self.vline.setBounds([None, None])
self.hline.setBounds([None, None])
Expand All @@ -325,6 +369,11 @@ def set_crosshair_range(self, new_range):
return

def set_crosshair_pen(self, pen):
"""
Sets the pyqtgraph compatible pen to be used for drawing the crosshair lines.
@param pen: pyqtgraph compatible pen to use
"""
self.crosshair.setPen(pen)
self.vline.setPen(pen)
self.hline.setPen(pen)
Expand Down

0 comments on commit 063d9c7

Please sign in to comment.