From 20b9d079ce39b96616b255bec476142113d2b4b4 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 25 Dec 2013 22:03:01 -0800 Subject: [PATCH 1/2] Nicer range for value histogram of integer images. When an ImageItem's data has an integer dtype, this patch ensures that each bin of the LUT histogram contains the same number of integer values, in order to avoid "spikes" in the histogram that are merely due to some bins covering more integer values than others. This commit needs testing (it was rebased from an old commit). --- pyqtgraph/graphicsItems/ImageItem.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pyqtgraph/graphicsItems/ImageItem.py b/pyqtgraph/graphicsItems/ImageItem.py index 120312ad..4e29b11c 100644 --- a/pyqtgraph/graphicsItems/ImageItem.py +++ b/pyqtgraph/graphicsItems/ImageItem.py @@ -1,3 +1,5 @@ +from __future__ import division + from ..Qt import QtGui, QtCore import numpy as np import collections @@ -295,7 +297,15 @@ class ImageItem(GraphicsObject): if self.image is None: return None,None stepData = self.image[::step, ::step] - hist = np.histogram(stepData, bins=bins) + if not np.iterable(bins): + mn = stepData.min() + mx = stepData.max() + if stepData.dtype.kind in "ui": # unsigned or signed int + # we want max - min to be a multiple of nbins + range = mn, mn + np.ceil((mx - mn) / bins) * bins + else: + range = mn, mx + hist = np.histogram(stepData, bins=bins, range=range) return hist[1][:-1], hist[0] def setPxMode(self, b): From e8dd3e6e5773c92317383e6b7cd74f9684d3c033 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Tue, 14 Jan 2014 22:22:50 -0500 Subject: [PATCH 2/2] ImageItem.getHistogram is more clever about constructing histograms: - integer dtype images now have integer-aligned bins, with bin number determined by a target value - step size is automatically chosen based on a target image size - bins and step arguments have default values 'auto' --- pyqtgraph/graphicsItems/ImageItem.py | 44 +++++++++++++++++++++------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/pyqtgraph/graphicsItems/ImageItem.py b/pyqtgraph/graphicsItems/ImageItem.py index 4e29b11c..9e40e325 100644 --- a/pyqtgraph/graphicsItems/ImageItem.py +++ b/pyqtgraph/graphicsItems/ImageItem.py @@ -289,23 +289,45 @@ class ImageItem(GraphicsObject): self.render() self.qimage.save(fileName, *args) - def getHistogram(self, bins=500, step=3): + def getHistogram(self, bins='auto', step='auto', targetImageSize=200, targetHistogramSize=500, **kwds): """Returns x and y arrays containing the histogram values for the current image. - The step argument causes pixels to be skipped when computing the histogram to save time. + For an explanation of the return format, see numpy.histogram(). + + The *step* argument causes pixels to be skipped when computing the histogram to save time. + If *step* is 'auto', then a step is chosen such that the analyzed data has + dimensions roughly *targetImageSize* for each axis. + + The *bins* argument and any extra keyword arguments are passed to + np.histogram(). If *bins* is 'auto', then a bin number is automatically + chosen based on the image characteristics: + + * Integer images will have approximately *targetHistogramSize* bins, + with each bin having an integer width. + * All other types will have *targetHistogramSize* bins. + This method is also used when automatically computing levels. """ if self.image is None: return None,None - stepData = self.image[::step, ::step] - if not np.iterable(bins): - mn = stepData.min() - mx = stepData.max() - if stepData.dtype.kind in "ui": # unsigned or signed int - # we want max - min to be a multiple of nbins - range = mn, mn + np.ceil((mx - mn) / bins) * bins + if step == 'auto': + step = (np.ceil(self.image.shape[0] / targetSize), + np.ceil(self.image.shape[1] / targetSize)) + if np.isscalar(step): + step = (step, step) + stepData = self.image[::step[0], ::step[1]] + + if bins == 'auto': + if stepData.dtype.kind in "ui": + mn = stepData.min() + mx = stepData.max() + step = np.ceil((mx-mn) / 500.) + bins = np.arange(mn, mx+1.01*step, step, dtype=np.int) else: - range = mn, mx - hist = np.histogram(stepData, bins=bins, range=range) + bins = 500 + + kwds['bins'] = bins + hist = np.histogram(stepData, **kwds) + return hist[1][:-1], hist[0] def setPxMode(self, b):