示例#1
0
    def render(self):
        #The same as pyqtgraph's ImageItem.render, with the exception that the makeARGB function is slightly different

        profile = debug.Profiler()
        if self.image is None or self.image.size == 0:
            return
        if isinstance(self.lut, Callable):
            lut = self.lut(self.image)
        else:
            lut = self.lut

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(QtCore.QPointF(0,0))
            x = self.mapToDevice(QtCore.QPointF(1,0))
            y = self.mapToDevice(QtCore.QPointF(0,1))
            w = Point(x-o).length()
            h = Point(y-o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return
            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))
            axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
            image = fn.downsample(self.image, xds, axis=axes[0])
            image = fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)
        else:
            image = self.image

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)

        if self.axisOrder == 'col-major':
            image = image.transpose((1, 0, 2)[:image.ndim])

        argb, alpha = makeARGBwithNaNs(image, lut=lut, levels=self.levels)
        self.qimage = fn.makeQImage(argb, alpha, transpose=False)
示例#2
0
    def render(self):
        # Convert data to QImage for display.

        profile = debug.Profiler()
        if self.image is None or self.image.size == 0:
            return
        if isinstance(self.lut, collections.Callable):
            lut = self.lut(self.image)
        else:
            lut = self.lut

        if self.logScale:
            image = self.image + 1
            with np.errstate(invalid="ignore"):
                image = image.astype(np.float)
                np.log(image, where=image >= 0, out=image)  # map to 0-255
        else:
            image = self.image

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(QPointF(0, 0))
            x = self.mapToDevice(QPointF(1, 0))
            y = self.mapToDevice(QPointF(0, 1))
            w = Point(x - o).length()
            h = Point(y - o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return
            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))
            axes = [1, 0] if self.axisOrder == "row-major" else [0, 1]
            image = fn.downsample(image, xds, axis=axes[0])
            image = fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)
        else:
            pass

        # if the image data is a small int, then we can combine levels + lut
        # into a single lut for better performance
        levels = self.levels
        if levels is not None and levels.ndim == 1 and image.dtype in (
                np.ubyte, np.uint16):
            if self._effectiveLut is None:
                eflsize = 2**(image.itemsize * 8)
                ind = np.arange(eflsize)
                minlev, maxlev = levels
                levdiff = maxlev - minlev
                levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
                if lut is None:
                    efflut = fn.rescaleData(ind,
                                            scale=255.0 / levdiff,
                                            offset=minlev,
                                            dtype=np.ubyte)
                else:
                    lutdtype = np.min_scalar_type(lut.shape[0] - 1)
                    efflut = fn.rescaleData(ind,
                                            scale=(lut.shape[0] - 1) / levdiff,
                                            offset=minlev,
                                            dtype=lutdtype,
                                            clip=(0, lut.shape[0] - 1))
                    efflut = lut[efflut]

                self._effectiveLut = efflut
            lut = self._effectiveLut
            levels = None

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)

        if self.axisOrder == "col-major":
            image = image.transpose((1, 0, 2)[:image.ndim])

        if self.logScale:
            with np.errstate(invalid="ignore"):
                levels = np.log(np.add(levels, 1))
            levels[0] = np.nanmax([levels[0], 0])

        argb, alpha = fn.makeARGB(image, lut=lut, levels=levels)
        self.qimage = fn.makeQImage(argb, alpha, transpose=False)
示例#3
0
def assertImageApproved(image, standardFile, message=None, **kwargs):
    """Check that an image test result matches a pre-approved standard.

    If the result does not match, then the user can optionally invoke a GUI
    to compare the images and decide whether to fail the test or save the new
    image as the standard.

    Run the test with the environment variable PYQTGRAPH_AUDIT=1 to bring up
    the auditing GUI.

    Parameters
    ----------
    image : (h, w, 4) ndarray
    standardFile : str
        The name of the approved test image to check against. This file name
        is relative to the root of the pyqtgraph test-data repository and will
        be automatically fetched.
    message : str
        A string description of the image. It is recommended to describe
        specific features that an auditor should look for when deciding whether
        to fail a test.

    Extra keyword arguments are used to set the thresholds for automatic image
    comparison (see ``assertImageMatch()``).
    """
    if isinstance(image, QtWidgets.QWidget):
        # just to be sure the widget size is correct (new window may be resized):
        QtWidgets.QApplication.processEvents()

        graphstate = scenegraphState(image, standardFile)
        image = getImageFromWidget(image)

    if message is None:
        code = inspect.currentframe().f_back.f_code
        message = "%s::%s" % (code.co_filename, code.co_name)

    # Make sure we have a test data repo available
    dataPath = getTestDataDirectory()

    # Read the standard image if it exists
    stdFileName = os.path.join(dataPath, standardFile + '.png')
    if not os.path.isfile(stdFileName):
        stdImage = None
    else:
        qimg = QtGui.QImage(stdFileName)
        qimg = qimg.convertToFormat(QtGui.QImage.Format.Format_RGBA8888)
        stdImage = fn.ndarray_from_qimage(qimg).copy()
        del qimg

    # If the test image does not match, then we go to audit if requested.
    try:
        if stdImage is None:
            raise Exception("No reference image saved for this test.")
        if image.shape[2] != stdImage.shape[2]:
            raise Exception(
                "Test result has different channel count than standard image"
                "(%d vs %d)" % (image.shape[2], stdImage.shape[2]))
        if image.shape != stdImage.shape:
            # Allow im1 to be an integer multiple larger than im2 to account
            # for high-resolution displays
            ims1 = np.array(image.shape).astype(float)
            ims2 = np.array(stdImage.shape).astype(float)
            sr = ims1 / ims2 if ims1[0] > ims2[0] else ims2 / ims1
            if (sr[0] != sr[1] or not np.allclose(sr, np.round(sr))
                    or sr[0] < 1):
                raise TypeError("Test result shape %s is not an integer factor"
                                " different than standard image shape %s." %
                                (ims1, ims2))
            sr = np.round(sr).astype(int)
            image = fn.downsample(image, sr[0],
                                  axis=(0, 1)).astype(image.dtype)

        assertImageMatch(image, stdImage, **kwargs)

        if bool(os.getenv('PYQTGRAPH_PRINT_TEST_STATE', False)):
            print(graphstate)

        if os.getenv('PYQTGRAPH_AUDIT_ALL') == '1':
            raise Exception(
                "Image test passed, but auditing due to PYQTGRAPH_AUDIT_ALL evnironment variable."
            )
    except Exception:
        if os.getenv('PYQTGRAPH_AUDIT') == '1' or os.getenv(
                'PYQTGRAPH_AUDIT_ALL') == '1':
            sys.excepthook(*sys.exc_info())
            getTester().test(image, stdImage, message)
            stdPath = os.path.dirname(stdFileName)
            print('Saving new standard image to "%s"' % stdFileName)
            if not os.path.isdir(stdPath):
                os.makedirs(stdPath)
            qimg = fn.ndarray_to_qimage(image,
                                        QtGui.QImage.Format.Format_RGBA8888)
            qimg.save(stdFileName)
            del qimg
        else:
            if stdImage is None:
                raise Exception("Test standard %s does not exist. Set "
                                "PYQTGRAPH_AUDIT=1 to add this image." %
                                stdFileName)
            if os.getenv('CI') is not None:
                standardFile = os.path.join(
                    os.getenv("SCREENSHOT_DIR", "screenshots"), standardFile)
                saveFailedTest(image, stdImage, standardFile)
            print(graphstate)
            raise
示例#4
0
    def render(self):
        #The same as pyqtgraph's ImageItem.render, with the exception that the makeARGB function is slightly different

        profile = debug.Profiler()
        if self.image is None or self.image.size == 0:
            return
        if isinstance(self.lut, Callable):
            lut = self.lut(self.image)
        else:
            lut = self.lut

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(QtCore.QPointF(0, 0))
            x = self.mapToDevice(QtCore.QPointF(1, 0))
            y = self.mapToDevice(QtCore.QPointF(0, 1))
            w = Point(x - o).length()
            h = Point(y - o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return
            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))
            axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
            image = fn.downsample(self.image, xds, axis=axes[0])
            image = fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)
        else:
            image = self.image

        # if the image data is a small int, then we can combine levels + lut
        # into a single lut for better performance
        levels = self.levels
        if levels is not None and levels.ndim == 1 and image.dtype in (
                np.ubyte, np.uint16):
            if self._effectiveLut is None:
                eflsize = 2**(image.itemsize * 8)
                ind = np.arange(eflsize)
                minlev, maxlev = levels
                levdiff = maxlev - minlev
                levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
                if lut is None:
                    efflut = fn.rescaleData(ind,
                                            scale=255. / levdiff,
                                            offset=minlev,
                                            dtype=np.ubyte)
                else:
                    lutdtype = np.min_scalar_type(lut.shape[0] - 1)
                    efflut = fn.rescaleData(ind,
                                            scale=(lut.shape[0] - 1) / levdiff,
                                            offset=minlev,
                                            dtype=lutdtype,
                                            clip=(0, lut.shape[0] - 1))
                    efflut = lut[efflut]

                self._effectiveLut = efflut
            lut = self._effectiveLut
            levels = None

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)

        if self.axisOrder == 'col-major':
            image = image.transpose((1, 0, 2)[:image.ndim])

        argb, alpha = makeARGBwithNaNs(image, lut=lut, levels=levels)
        self.qimage = fn.makeQImage(argb, alpha, transpose=False)
示例#5
0
    def render(self):
        # Convert data to QImage for display.

        profile = debug.Profiler()
        if self.image is None or self.image.size == 0:
            return

        # Request a lookup table if this image has only one channel
        if self.image.ndim == 2 or self.image.shape[2] == 1:
            if isinstance(self.lut, Callable):
                lut = self.lut(self.image)
            else:
                lut = self.lut
        else:
            lut = None

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(QtCore.QPointF(0, 0))
            x = self.mapToDevice(QtCore.QPointF(1, 0))
            y = self.mapToDevice(QtCore.QPointF(0, 1))

            # Check if graphics view is too small to render anything
            if o is None or x is None or y is None:
                return

            w = Point(x - o).length()
            h = Point(y - o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return
            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))
            axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
            image = fn.downsample(self.image, xds, axis=axes[0])
            image = fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)

            # Check if downsampling reduced the image size to zero due to inf values.
            if image.size == 0:
                return
        else:
            image = self.image

        # if the image data is a small int, then we can combine levels + lut
        # into a single lut for better performance
        levels = self.levels
        if levels is not None and levels.ndim == 1 and image.dtype in (
                np.ubyte, np.uint16):
            if self._effectiveLut is None:
                eflsize = 2**(image.itemsize * 8)
                ind = np.arange(eflsize)
                minlev, maxlev = levels
                levdiff = maxlev - minlev
                levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
                if lut is None:
                    efflut = fn.rescaleData(ind,
                                            scale=255. / levdiff,
                                            offset=minlev,
                                            dtype=np.ubyte)
                else:
                    lutdtype = np.min_scalar_type(lut.shape[0] - 1)
                    efflut = fn.rescaleData(ind,
                                            scale=(lut.shape[0] - 1) / levdiff,
                                            offset=minlev,
                                            dtype=lutdtype,
                                            clip=(0, lut.shape[0] - 1))
                    efflut = lut[efflut]

                self._effectiveLut = efflut
            lut = self._effectiveLut
            levels = None

        # Convert single-channel image to 2D array
        if image.ndim == 3 and image.shape[-1] == 1:
            image = image[..., 0]

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)
        if self.axisOrder == 'col-major':
            image = image.transpose((1, 0, 2)[:image.ndim])

        # Get bounds of view box
        viewBounds = np.array(self.getViewBox().viewRange())
        viewBounds[0][0] = max(viewBounds[0][0] - 1, 0)
        viewBounds[0][1] = min(viewBounds[0][1] + 1, image.shape[1])
        viewBounds[1][0] = max(viewBounds[1][0] - 1, 0)
        viewBounds[1][1] = min(viewBounds[1][1] + 1, image.shape[0])

        # Send image to ARGB worker
        self.imageARGBWorker.prepareForNewImage(image, lut, levels, viewBounds,
                                                self.onlyRenderVisible)
        self.sigImageReadyForARGB.emit()
示例#6
0
	def render(self):
		# Convert data to QImage for display.
		
		profile = debug.Profiler()
		if self.image is None or self.image.size == 0:
			return
		
		# Request a lookup table if this image has only one channel
		if self.image.ndim == 2 or self.image.shape[2] == 1:
			if isinstance(self.lut, collections.Callable):
				lut = self.lut(self.image)
			else:
				lut = self.lut
		else:
			lut = None

		if self.autoDownsample:
			# reduce dimensions of image based on screen resolution
			o = self.mapToDevice(QtCore.QPointF(0,0))
			x = self.mapToDevice(QtCore.QPointF(1,0))
			y = self.mapToDevice(QtCore.QPointF(0,1))
			w = Point(x-o).length()
			h = Point(y-o).length()
			if w == 0 or h == 0:
				self.qimage = None
				return
			xds = max(1, int(1.0 / w))
			yds = max(1, int(1.0 / h))
			axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
			image = fn.downsample(self.image, xds, axis=axes[0])
			image = fn.downsample(image, yds, axis=axes[1])
			self._lastDownsample = (xds, yds)
		else:
			image = self.image

		# if the image data is a small int, then we can combine levels + lut
		# into a single lut for better performance
		levels = self.levels
		if levels is not None and levels.ndim == 1 and image.dtype in (np.ubyte, np.uint16):
			if self._effectiveLut is None:
				eflsize = 2**(image.itemsize*8)
				ind = np.arange(eflsize)
				minlev, maxlev = levels
				levdiff = maxlev - minlev
				levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
				if lut is None:
					efflut = fn.rescaleData(ind, scale=255./levdiff, 
											offset=minlev, dtype=np.ubyte)
				else:
					lutdtype = np.min_scalar_type(lut.shape[0]-1)
					efflut = fn.rescaleData(ind, scale=(lut.shape[0]-1)/levdiff,
											offset=minlev, dtype=lutdtype, clip=(0, lut.shape[0]-1))
					efflut = lut[efflut]
				
				self._effectiveLut = efflut
			lut = self._effectiveLut
			levels = None
		
		# Convert single-channel image to 2D array
		if image.ndim == 3 and image.shape[-1] == 1:
			image = image[..., 0]
		
		# Assume images are in column-major order for backward compatibility
		# (most images are in row-major order)
		if self.axisOrder == 'col-major':
			image = image.transpose((1, 0, 2)[:image.ndim])
		
		argb, alpha = fn.makeARGB(image, lut=lut, levels=levels)

		if self.alpha is not None:
			argb[:,:,3] = self.alpha.T

		self.qimage = fn.makeQImage(argb, True, transpose=False)