Пример #1
0
    def computeProfile(self, item):
        if not isinstance(item, items.ImageBase):
            raise TypeError("Unexpected class %s" % type(item))

        from silx.image.bilinear import BilinearImage

        origin = item.getOrigin()
        scale = item.getScale()
        method = self.getProfileMethod()
        lineWidth = self.getProfileLineWidth()
        currentData = item.getValueData(copy=False)

        roiInfo = self._getRoiInfo()
        roiStart, roiEnd, _lineProjectionMode = roiInfo

        startPt = ((roiStart[1] - origin[1]) / scale[1],
                   (roiStart[0] - origin[0]) / scale[0])
        endPt = ((roiEnd[1] - origin[1]) / scale[1],
                 (roiEnd[0] - origin[0]) / scale[0])

        if numpy.array_equal(startPt, endPt):
            return None

        bilinear = BilinearImage(currentData)
        profile = bilinear.profile_line((startPt[0] - 0.5, startPt[1] - 0.5),
                                        (endPt[0] - 0.5, endPt[1] - 0.5),
                                        lineWidth,
                                        method=method)

        # Compute the line size
        lineSize = numpy.sqrt((roiEnd[1] - roiStart[1])**2 +
                              (roiEnd[0] - roiStart[0])**2)
        coords = numpy.linspace(0,
                                lineSize,
                                len(profile),
                                endpoint=True,
                                dtype=numpy.float32)

        title = _lineProfileTitle(*roiStart, *roiEnd)
        title = title + "; width = %d" % lineWidth
        xLabel = "√({xlabel}²+{ylabel}²)"
        yLabel = str(method).capitalize()

        # Use the axis names from the original plot
        profileManager = self.getProfileManager()
        plot = profileManager.getPlotWidget()
        xLabel = _relabelAxes(plot, xLabel)
        title = _relabelAxes(plot, title)

        data = core.CurveProfileData(
            coords=coords,
            profile=profile,
            title=title,
            xLabel=xLabel,
            yLabel=yLabel,
        )
        return data
def resize_image(original_image, new_shape):
    """Return resized image

    :param original_image:
    :param tuple(int) new_shape: New image shape (rows, columns)
    :return: New resized image, as a 2D numpy array
    """
    bilinimg = BilinearImage(original_image)

    row_array, column_array = numpy.meshgrid(
        numpy.linspace(0, original_image.shape[0], new_shape[0]),
        numpy.linspace(0, original_image.shape[1], new_shape[1]),
        indexing="ij")

    interpolated_values = bilinimg.map_coordinates((row_array, column_array))

    interpolated_values.shape = new_shape
    return interpolated_values
Пример #3
0
def resize_image(original_image, new_shape):
    """Return resized image

    :param original_image:
    :param tuple(int) new_shape: New image shape (rows, columns)
    :return: New resized image, as a 2D numpy array
    """
    bilinimg = BilinearImage(original_image)

    row_array, column_array = numpy.meshgrid(
            numpy.linspace(0, original_image.shape[0], new_shape[0]),
            numpy.linspace(0, original_image.shape[1], new_shape[1]),
            indexing="ij")

    interpolated_values = bilinimg.map_coordinates((row_array, column_array))

    interpolated_values.shape = new_shape
    return interpolated_values
Пример #4
0
def createProfile(roiInfo, currentData, origin, scale, lineWidth, method):
    """Create the profile line for the the given image.

    :param roiInfo: information about the ROI: start point, end point and
        type ("X", "Y", "D")
    :param numpy.ndarray currentData: the 2D image or the 3D stack of images
        on which we compute the profile.
    :param origin: (ox, oy) the offset from origin
    :type origin: 2-tuple of float
    :param scale: (sx, sy) the scale to use
    :type scale: 2-tuple of float
    :param int lineWidth: width of the profile line
    :param str method: method to compute the profile. Can be 'mean' or 'sum'
    :return: `coords, profile, area, profileName, xLabel`, where:
        - coords is the X coordinate to use to display the profile
        - profile is a 2D array of the profiles of the stack of images.
          For a single image, the profile is a curve, so this parameter
          has a shape *(1, len(curve))*
        - area is a tuple of two 1D arrays with 4 values each. They represent
          the effective ROI area corners in plot coords.
        - profileName is a string describing the ROI, meant to be used as
          title of the profile plot
        - xLabel the label for X in the profile window

    :rtype: tuple(ndarray,ndarray,(ndarray,ndarray),str)
    """
    if currentData is None or roiInfo is None or lineWidth is None:
        raise ValueError("createProfile called with invalide arguments")

    # force 3D data (stack of images)
    if len(currentData.shape) == 2:
        currentData3D = currentData.reshape((1, ) + currentData.shape)
    elif len(currentData.shape) == 3:
        currentData3D = currentData

    roiWidth = max(1, lineWidth)
    roiStart, roiEnd, lineProjectionMode = roiInfo

    if lineProjectionMode == 'X':  # Horizontal profile on the whole image
        profile, area = _alignedFullProfile(currentData3D,
                                            origin,
                                            scale,
                                            roiStart[1],
                                            roiWidth,
                                            axis=0,
                                            method=method)

        coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
        coords = coords * scale[0] + origin[0]

        yMin, yMax = min(area[1]), max(area[1]) - 1
        if roiWidth <= 1:
            profileName = 'Y = %g' % yMin
        else:
            profileName = 'Y = [%g, %g]' % (yMin, yMax)
        xLabel = 'X'

    elif lineProjectionMode == 'Y':  # Vertical profile on the whole image
        profile, area = _alignedFullProfile(currentData3D,
                                            origin,
                                            scale,
                                            roiStart[0],
                                            roiWidth,
                                            axis=1,
                                            method=method)

        coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
        coords = coords * scale[1] + origin[1]

        xMin, xMax = min(area[0]), max(area[0]) - 1
        if roiWidth <= 1:
            profileName = 'X = %g' % xMin
        else:
            profileName = 'X = [%g, %g]' % (xMin, xMax)
        xLabel = 'Y'

    else:  # Free line profile

        # Convert start and end points in image coords as (row, col)
        startPt = ((roiStart[1] - origin[1]) / scale[1],
                   (roiStart[0] - origin[0]) / scale[0])
        endPt = ((roiEnd[1] - origin[1]) / scale[1],
                 (roiEnd[0] - origin[0]) / scale[0])

        if (int(startPt[0]) == int(endPt[0])
                or int(startPt[1]) == int(endPt[1])):
            # Profile is aligned with one of the axes

            # Convert to int
            startPt = int(startPt[0]), int(startPt[1])
            endPt = int(endPt[0]), int(endPt[1])

            # Ensure startPt <= endPt
            if startPt[0] > endPt[0] or startPt[1] > endPt[1]:
                startPt, endPt = endPt, startPt

            if startPt[0] == endPt[0]:  # Row aligned
                rowRange = (int(startPt[0] + 0.5 - 0.5 * roiWidth),
                            int(startPt[0] + 0.5 + 0.5 * roiWidth))
                colRange = startPt[1], endPt[1] + 1
                profile = _alignedPartialProfile(currentData3D,
                                                 rowRange,
                                                 colRange,
                                                 axis=0,
                                                 method=method)

            else:  # Column aligned
                rowRange = startPt[0], endPt[0] + 1
                colRange = (int(startPt[1] + 0.5 - 0.5 * roiWidth),
                            int(startPt[1] + 0.5 + 0.5 * roiWidth))
                profile = _alignedPartialProfile(currentData3D,
                                                 rowRange,
                                                 colRange,
                                                 axis=1,
                                                 method=method)

            # Convert ranges to plot coords to draw ROI area
            area = (numpy.array(
                (colRange[0], colRange[1], colRange[1], colRange[0]),
                dtype=numpy.float32) * scale[0] + origin[0],
                    numpy.array(
                        (rowRange[0], rowRange[0], rowRange[1], rowRange[1]),
                        dtype=numpy.float32) * scale[1] + origin[1])

        else:  # General case: use bilinear interpolation

            # Ensure startPt <= endPt
            if (startPt[1] > endPt[1]
                    or (startPt[1] == endPt[1] and startPt[0] > endPt[0])):
                startPt, endPt = endPt, startPt

            profile = []
            for slice_idx in range(currentData3D.shape[0]):
                bilinear = BilinearImage(currentData3D[slice_idx, :, :])

                profile.append(
                    bilinear.profile_line((startPt[0] - 0.5, startPt[1] - 0.5),
                                          (endPt[0] - 0.5, endPt[1] - 0.5),
                                          roiWidth,
                                          method=method))
            profile = numpy.array(profile)

            # Extend ROI with half a pixel on each end, and
            # Convert back to plot coords (x, y)
            length = numpy.sqrt((endPt[0] - startPt[0])**2 +
                                (endPt[1] - startPt[1])**2)
            dRow = (endPt[0] - startPt[0]) / length
            dCol = (endPt[1] - startPt[1]) / length

            # Extend ROI with half a pixel on each end
            roiStartPt = startPt[0] - 0.5 * dRow, startPt[1] - 0.5 * dCol
            roiEndPt = endPt[0] + 0.5 * dRow, endPt[1] + 0.5 * dCol

            # Rotate deltas by 90 degrees to apply line width
            dRow, dCol = dCol, -dRow

            area = (numpy.array(
                (roiStartPt[1] - 0.5 * roiWidth * dCol, roiStartPt[1] +
                 0.5 * roiWidth * dCol, roiEndPt[1] + 0.5 * roiWidth * dCol,
                 roiEndPt[1] - 0.5 * roiWidth * dCol),
                dtype=numpy.float32) * scale[0] + origin[0],
                    numpy.array(
                        (roiStartPt[0] - 0.5 * roiWidth * dRow, roiStartPt[0] +
                         0.5 * roiWidth * dRow, roiEndPt[0] + 0.5 * roiWidth *
                         dRow, roiEndPt[0] - 0.5 * roiWidth * dRow),
                        dtype=numpy.float32) * scale[1] + origin[1])

        # Convert start and end points back to plot coords
        y0 = startPt[0] * scale[1] + origin[1]
        x0 = startPt[1] * scale[0] + origin[0]
        y1 = endPt[0] * scale[1] + origin[1]
        x1 = endPt[1] * scale[0] + origin[0]

        if startPt[1] == endPt[1]:
            profileName = 'X = %g; Y = [%g, %g]' % (x0, y0, y1)
            coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
            coords = coords * scale[1] + y0
            xLabel = 'Y'

        elif startPt[0] == endPt[0]:
            profileName = 'Y = %g; X = [%g, %g]' % (y0, x0, x1)
            coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
            coords = coords * scale[0] + x0
            xLabel = 'X'

        else:
            m = (y1 - y0) / (x1 - x0)
            b = y0 - m * x0
            profileName = 'y = %g * x %+g ; width=%d' % (m, b, roiWidth)
            coords = numpy.linspace(x0,
                                    x1,
                                    len(profile[0]),
                                    endpoint=True,
                                    dtype=numpy.float32)
            xLabel = 'X'

    return coords, profile, area, profileName, xLabel
Пример #5
0
def createProfile(roiInfo, currentData, origin, scale, lineWidth, method):
    """Create the profile line for the the given image.

    :param roiInfo: information about the ROI: start point, end point and
        type ("X", "Y", "D")
    :param numpy.ndarray currentData: the 2D image or the 3D stack of images
        on which we compute the profile.
    :param origin: (ox, oy) the offset from origin
    :type origin: 2-tuple of float
    :param scale: (sx, sy) the scale to use
    :type scale: 2-tuple of float
    :param int lineWidth: width of the profile line
    :param str method: method to compute the profile. Can be 'mean' or 'sum'
    :return: `coords, profile, area, profileName, xLabel`, where:
        - coords is the X coordinate to use to display the profile
        - profile is a 2D array of the profiles of the stack of images.
          For a single image, the profile is a curve, so this parameter
          has a shape *(1, len(curve))*
        - area is a tuple of two 1D arrays with 4 values each. They represent
          the effective ROI area corners in plot coords.
        - profileName is a string describing the ROI, meant to be used as
          title of the profile plot
        - xLabel the label for X in the profile window

    :rtype: tuple(ndarray,ndarray,(ndarray,ndarray),str)
    """
    if currentData is None or roiInfo is None or lineWidth is None:
        raise ValueError("createProfile called with invalide arguments")

    # force 3D data (stack of images)
    if len(currentData.shape) == 2:
        currentData3D = currentData.reshape((1,) + currentData.shape)
    elif len(currentData.shape) == 3:
        currentData3D = currentData

    roiWidth = max(1, lineWidth)
    roiStart, roiEnd, lineProjectionMode = roiInfo

    if lineProjectionMode == 'X':  # Horizontal profile on the whole image
        profile, area = _alignedFullProfile(currentData3D,
                                            origin, scale,
                                            roiStart[1], roiWidth,
                                            axis=0,
                                            method=method)

        coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
        coords = coords * scale[0] + origin[0]

        yMin, yMax = min(area[1]), max(area[1]) - 1
        if roiWidth <= 1:
            profileName = 'Y = %g' % yMin
        else:
            profileName = 'Y = [%g, %g]' % (yMin, yMax)
        xLabel = 'X'

    elif lineProjectionMode == 'Y':  # Vertical profile on the whole image
        profile, area = _alignedFullProfile(currentData3D,
                                            origin, scale,
                                            roiStart[0], roiWidth,
                                            axis=1,
                                            method=method)

        coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
        coords = coords * scale[1] + origin[1]

        xMin, xMax = min(area[0]), max(area[0]) - 1
        if roiWidth <= 1:
            profileName = 'X = %g' % xMin
        else:
            profileName = 'X = [%g, %g]' % (xMin, xMax)
        xLabel = 'Y'

    else:  # Free line profile

        # Convert start and end points in image coords as (row, col)
        startPt = ((roiStart[1] - origin[1]) / scale[1],
                   (roiStart[0] - origin[0]) / scale[0])
        endPt = ((roiEnd[1] - origin[1]) / scale[1],
                 (roiEnd[0] - origin[0]) / scale[0])

        if (int(startPt[0]) == int(endPt[0]) or
                int(startPt[1]) == int(endPt[1])):
            # Profile is aligned with one of the axes

            # Convert to int
            startPt = int(startPt[0]), int(startPt[1])
            endPt = int(endPt[0]), int(endPt[1])

            # Ensure startPt <= endPt
            if startPt[0] > endPt[0] or startPt[1] > endPt[1]:
                startPt, endPt = endPt, startPt

            if startPt[0] == endPt[0]:  # Row aligned
                rowRange = (int(startPt[0] + 0.5 - 0.5 * roiWidth),
                            int(startPt[0] + 0.5 + 0.5 * roiWidth))
                colRange = startPt[1], endPt[1] + 1
                profile = _alignedPartialProfile(currentData3D,
                                                 rowRange, colRange,
                                                 axis=0,
                                                 method=method)

            else:  # Column aligned
                rowRange = startPt[0], endPt[0] + 1
                colRange = (int(startPt[1] + 0.5 - 0.5 * roiWidth),
                            int(startPt[1] + 0.5 + 0.5 * roiWidth))
                profile = _alignedPartialProfile(currentData3D,
                                                 rowRange, colRange,
                                                 axis=1,
                                                 method=method)

            # Convert ranges to plot coords to draw ROI area
            area = (
                numpy.array(
                    (colRange[0], colRange[1], colRange[1], colRange[0]),
                    dtype=numpy.float32) * scale[0] + origin[0],
                numpy.array(
                    (rowRange[0], rowRange[0], rowRange[1], rowRange[1]),
                    dtype=numpy.float32) * scale[1] + origin[1])

        else:  # General case: use bilinear interpolation

            # Ensure startPt <= endPt
            if (startPt[1] > endPt[1] or (
                    startPt[1] == endPt[1] and startPt[0] > endPt[0])):
                startPt, endPt = endPt, startPt

            profile = []
            for slice_idx in range(currentData3D.shape[0]):
                bilinear = BilinearImage(currentData3D[slice_idx, :, :])

                profile.append(bilinear.profile_line(
                    (startPt[0] - 0.5, startPt[1] - 0.5),
                    (endPt[0] - 0.5, endPt[1] - 0.5),
                    roiWidth,
                    method=method))
            profile = numpy.array(profile)

            # Extend ROI with half a pixel on each end, and
            # Convert back to plot coords (x, y)
            length = numpy.sqrt((endPt[0] - startPt[0]) ** 2 +
                                (endPt[1] - startPt[1]) ** 2)
            dRow = (endPt[0] - startPt[0]) / length
            dCol = (endPt[1] - startPt[1]) / length

            # Extend ROI with half a pixel on each end
            roiStartPt = startPt[0] - 0.5 * dRow, startPt[1] - 0.5 * dCol
            roiEndPt = endPt[0] + 0.5 * dRow, endPt[1] + 0.5 * dCol

            # Rotate deltas by 90 degrees to apply line width
            dRow, dCol = dCol, -dRow

            area = (
                numpy.array((roiStartPt[1] - 0.5 * roiWidth * dCol,
                             roiStartPt[1] + 0.5 * roiWidth * dCol,
                             roiEndPt[1] + 0.5 * roiWidth * dCol,
                             roiEndPt[1] - 0.5 * roiWidth * dCol),
                            dtype=numpy.float32) * scale[0] + origin[0],
                numpy.array((roiStartPt[0] - 0.5 * roiWidth * dRow,
                             roiStartPt[0] + 0.5 * roiWidth * dRow,
                             roiEndPt[0] + 0.5 * roiWidth * dRow,
                             roiEndPt[0] - 0.5 * roiWidth * dRow),
                            dtype=numpy.float32) * scale[1] + origin[1])

        # Convert start and end points back to plot coords
        y0 = startPt[0] * scale[1] + origin[1]
        x0 = startPt[1] * scale[0] + origin[0]
        y1 = endPt[0] * scale[1] + origin[1]
        x1 = endPt[1] * scale[0] + origin[0]

        if startPt[1] == endPt[1]:
            profileName = 'X = %g; Y = [%g, %g]' % (x0, y0, y1)
            coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
            coords = coords * scale[1] + y0
            xLabel = 'Y'

        elif startPt[0] == endPt[0]:
            profileName = 'Y = %g; X = [%g, %g]' % (y0, x0, x1)
            coords = numpy.arange(len(profile[0]), dtype=numpy.float32)
            coords = coords * scale[0] + x0
            xLabel = 'X'

        else:
            m = (y1 - y0) / (x1 - x0)
            b = y0 - m * x0
            profileName = 'y = %g * x %+g ; width=%d' % (m, b, roiWidth)
            coords = numpy.linspace(x0, x1, len(profile[0]),
                                    endpoint=True,
                                    dtype=numpy.float32)
            xLabel = 'X'

    return coords, profile, area, profileName, xLabel
Пример #6
0
    def updateProfile(self):
        """Update the displayed profile and profile ROI.

        This uses the current active image of the plot and the current ROI.
        """

        # Clean previous profile area, and previous curve
        self.plot.remove(self._POLYGON_LEGEND, kind='item')
        self.profileWindow.clear()
        self.profileWindow.setGraphTitle('')
        self.profileWindow.setGraphXLabel('X')
        self.profileWindow.setGraphYLabel('Y')

        if self._roiInfo is None:
            return

        imageData = self.plot.getActiveImage()
        if imageData is None:
            return

        data, params = imageData[0], imageData[4]
        origin, scale = params['origin'], params['scale']
        zActiveImage = params['z']

        roiWidth = max(1, self.lineWidthSpinBox.value())
        roiStart, roiEnd, lineProjectionMode = self._roiInfo

        if lineProjectionMode == 'X':  # Horizontal profile on the whole image
            profile, area = self._alignedFullProfile(
                data, origin, scale, roiStart[1], roiWidth, axis=0)

            yMin, yMax = min(area[1]), max(area[1]) - 1
            if roiWidth <= 1:
                profileName = 'Y = %g' % yMin
            else:
                profileName = 'Y = [%g, %g]' % (yMin, yMax)
            xLabel = 'Columns'

        elif lineProjectionMode == 'Y':  # Vertical profile on the whole image
            profile, area = self._alignedFullProfile(
                data, origin, scale, roiStart[0], roiWidth, axis=1)

            xMin, xMax = min(area[0]), max(area[0]) - 1
            if roiWidth <= 1:
                profileName = 'X = %g' % xMin
            else:
                profileName = 'X = [%g, %g]' % (xMin, xMax)
            xLabel = 'Rows'

        else:  # Free line profile

            # Convert start and end points in image coords as (row, col)
            startPt = ((roiStart[1] - origin[1]) / scale[1],
                       (roiStart[0] - origin[0]) / scale[0])
            endPt = ((roiEnd[1] - origin[1]) / scale[1],
                     (roiEnd[0] - origin[0]) / scale[0])

            if (int(startPt[0]) == int(endPt[0]) or
                    int(startPt[1]) == int(endPt[1])):
                # Profile is aligned with one of the axes

                # Convert to int
                startPt = int(startPt[0]), int(startPt[1])
                endPt = int(endPt[0]), int(endPt[1])

                # Ensure startPt <= endPt
                if startPt[0] > endPt[0] or startPt[1] > endPt[1]:
                    startPt, endPt = endPt, startPt

                if startPt[0] == endPt[0]:  # Row aligned
                    rowRange = (int(startPt[0] + 0.5 - 0.5 * roiWidth),
                                int(startPt[0] + 0.5 + 0.5 * roiWidth))
                    colRange = startPt[1], endPt[1] + 1
                    profile = self._alignedPartialProfile(
                        data, rowRange, colRange, axis=0)

                else:  # Column aligned
                    rowRange = startPt[0], endPt[0] + 1
                    colRange = (int(startPt[1] + 0.5 - 0.5 * roiWidth),
                                int(startPt[1] + 0.5 + 0.5 * roiWidth))
                    profile = self._alignedPartialProfile(
                        data, rowRange, colRange, axis=1)

                # Convert ranges to plot coords to draw ROI area
                area = (
                    numpy.array(
                        (colRange[0], colRange[1], colRange[1], colRange[0]),
                        dtype=numpy.float32) * scale[0] + origin[0],
                    numpy.array(
                        (rowRange[0], rowRange[0], rowRange[1], rowRange[1]),
                        dtype=numpy.float32) * scale[1] + origin[1])

            else:  # General case: use bilinear interpolation

                # Ensure startPt <= endPt
                if (startPt[1] > endPt[1] or (
                        startPt[1] == endPt[1] and startPt[0] > endPt[0])):
                    startPt, endPt = endPt, startPt

                bilinear = BilinearImage(data)

                # Offset start/end positions of 0.5 pixel to use pixel center
                # rather than pixel lower left corner for interpolation
                # This is only valid if image is displayed with nearest.
                profile = bilinear.profile_line(
                    (startPt[0] - 0.5, startPt[1] - 0.5),
                    (endPt[0] - 0.5, endPt[1] - 0.5),
                    roiWidth)

                # Extend ROI with half a pixel on each end, and
                # Convert back to plot coords (x, y)
                length = numpy.sqrt((endPt[0] - startPt[0]) ** 2 +
                                    (endPt[1] - startPt[1]) ** 2)
                dRow = (endPt[0] - startPt[0]) / length
                dCol = (endPt[1] - startPt[1]) / length

                # Extend ROI with half a pixel on each end
                startPt = startPt[0] - 0.5 * dRow, startPt[1] - 0.5 * dCol
                endPt = endPt[0] + 0.5 * dRow, endPt[1] + 0.5 * dCol

                # Rotate deltas by 90 degrees to apply line width
                dRow, dCol = dCol, -dRow

                area = (
                    numpy.array((startPt[1] - 0.5 * roiWidth * dCol,
                                 startPt[1] + 0.5 * roiWidth * dCol,
                                 endPt[1] + 0.5 * roiWidth * dCol,
                                 endPt[1] - 0.5 * roiWidth * dCol),
                                dtype=numpy.float32) * scale[0] + origin[0],
                    numpy.array((startPt[0] - 0.5 * roiWidth * dRow,
                                 startPt[0] + 0.5 * roiWidth * dRow,
                                 endPt[0] + 0.5 * roiWidth * dRow,
                                 endPt[0] - 0.5 * roiWidth * dRow),
                                dtype=numpy.float32) * scale[1] + origin[1])

            y0, x0 = startPt
            y1, x1 = endPt
            if x1 == x0 or y1 == y0:
                profileName = 'From (%g, %g) to (%g, %g)' % (x0, y0, x1, y1)
            else:
                m = (y1 - y0) / (x1 - x0)
                b = y0 - m * x0
                profileName = 'y = %g * x %+g ; width=%d' % (m, b, roiWidth)
            xLabel = 'Distance'

        coords = numpy.arange(len(profile), dtype=numpy.float32)
        # TODO coords in plot coords?

        self.profileWindow.setGraphTitle(profileName)
        self.profileWindow.addCurve(coords, profile,
                                    legend=profileName,
                                    xlabel=xLabel,
                                    color=self.overlayColor)

        self.plot.addItem(area[0], area[1],
                          legend=self._POLYGON_LEGEND,
                          color=self.overlayColor,
                          shape='polygon', fill=True,
                          replace=False, z=zActiveImage + 1)

        if self._ownProfileWindow and not self.profileWindow.isVisible():
            # If profile window was created in this widget,
            # it tries to avoid overlapping this widget when shown
            winGeom = self.window().frameGeometry()
            qapp = qt.QApplication.instance()
            screenGeom = qapp.desktop().availableGeometry(self)

            spaceOnLeftSide = winGeom.left()
            spaceOnRightSide = screenGeom.width() - winGeom.right()

            profileWindowWidth = self.profileWindow.frameGeometry().width()
            if (profileWindowWidth < spaceOnRightSide or
                    spaceOnRightSide > spaceOnLeftSide):
                # Place profile on the right
                self.profileWindow.move(winGeom.right(), winGeom.top())
            else:
                # Not enough place on the right, place profile on the left
                self.profileWindow.move(
                    max(0, winGeom.left() - profileWindowWidth), winGeom.top())

            self.profileWindow.show()