Пример #1
0
 def beam_position(self):
     xprofile, yprofile = xy_projections(self.image, self.ROI_center,
                                         self.ROI_width)
     x, y = CFWHM(xprofile), CFWHM(yprofile)
     return x, y
Пример #2
0
 def SNR(self):
     xprofile, yprofile = xy_projections(self.image, self.ROI_center,
                                         self.ROI_width)
     return (SNR(xprofile) + SNR(yprofile)) / 2
    def OnPaint(self, event):
        """Called by WX whenever the contents of the window
        needs re-rendering. E.g. when the window is brought to front,
        uncovered, restored from minimized state."""
        debug("OnPaint")

        from numpy import rint, array, minimum, uint8, ndarray, isnan, nan

        dc = wx.PaintDC(self)
        ##self.PrepareDC(dc)

        image = self.values["image"]
        debug("beam profile: image %r" % (image.shape, ))
        pixelsize = image.pixelsize
        # Clip to ROI (region of interest)
        cx, cy = self.values["x_ROI_center"], self.values["y_ROI_center"]
        w = h = self.values["ROI_width"]
        W, H = self.ClientSize
        if W > H: w = h / H * W
        if W < H: h = w / W * H
        ROI = xmin, xmax, ymin, ymax = cx - w / 2, cx + w / 2, cy - h / 2, cy + h / 2
        ixmin, ixmax, iymin, iymax = rint(array(ROI) / pixelsize).astype(int)
        ROI = xmin, xmax, ymin, ymax = array([ixmin, ixmax, iymin, iymax
                                              ]) * pixelsize
        w, h = xmax - xmin, ymax - ymin
        image_ROI = image[ixmin:ixmax, iymin:iymax]

        # Compress the dynamic range from 0...saturation_level to 0...256.
        scale = 255. / max(self.values["saturation_level"], 1)
        image = minimum(image_ROI * scale, 255).astype(uint8)

        # Convert from gray scale to  RGB format if needed.
        if image.ndim < 3:
            w, h = image.shape[-2:]
            RGB = ndarray((3, w, h), uint8, order="F")
            RGB[0], RGB[1], RGB[2] = image, image, image
            image = RGB

        # Mark overloaded pixels.
        overload_level = 65535
        mask_color = (255, 0, 0)
        mask_opacity = 1.0
        mask = image_ROI >= overload_level
        R, G, B = image
        r, g, b = mask_color
        x = mask_opacity
        R[mask] = (1 - x) * R[mask] + x * r
        G[mask] = (1 - x) * G[mask] + x * g
        B[mask] = (1 - x) * B[mask] + x * b
        ##image = array([R,G,B]) # needed?

        # Convert image from numpy to WX image format.
        w, h = image.shape[-2:]
        image = wx.ImageFromData(w, h, image)

        # Scale the image to fit into the window.
        W, H = self.ClientSize

        if len(self.values["image"]) > 0:
            ##scalefactor = min(float(W)/max(w,1),float(H)/max(h,1))
            ##W = rint(w*scalefactor); H = rint(h*scalefactor)
            image = image.Scale(W, H)
            dc.DrawBitmap(wx.BitmapFromImage(image), 0, 0)

        # Draw the FWHM with dimensions box around the beam center,
        # horizontal and vertcal beam projections or sections on the left and
        # bottom edge of the image
        cx, cy = self.values["x_ROI_center"], self.values["y_ROI_center"]
        d = self.values["ROI_width"]
        ROI = cx - d / 2, cx + d / 2, cy - d / 2, cy + d / 2
        ROI = rint(array(ROI) / pixelsize) * pixelsize
        ROI_xmin, ROI_xmax, ROI_ymin, ROI_ymax = ROI
        xprofile, yprofile = xy_projections(self.values["image"], (cx, cy), d)

        xscale = float(W) / max(w, 1) / pixelsize
        xoffset = -xmin * xscale
        yscale = float(H) / max(h, 1) / pixelsize
        yoffset = (-ymin) * yscale

        # Draw a crosshair marking the nominal beam center.
        crosshair_color = wx.Colour(0, 190, 0)
        dc.SetPen(wx.Pen(crosshair_color, 1))
        l = 0.2  # crosshair size in mm
        x = self.values["x_nominal"] * xscale + xoffset
        y = self.values["y_nominal"] * yscale + yoffset
        rx, ry = l / 2 * xscale, l / 2 * yscale
        dc.DrawLines([(x - rx, y), (x + rx, y)])
        dc.DrawLines([(x, y - ry), (x, y + ry)])

        # Draw horizontal profile at the bottom edge of the image.
        profile_color = wx.Colour(255, 0, 255)
        dc.SetPen(wx.Pen(profile_color, 1))
        x = xvals(xprofile)
        I = yvals(xprofile)
        Imax = max(I) if len(I) > 0 else nan
        if Imax == 0: Imax = 1
        Iscale = -0.35 * (ROI_ymax - ROI_ymin) * xscale / Imax
        Ioffset = ROI_ymax * yscale + yoffset
        lines = []
        for i in range(0, len(x) - 1):
            if not isnan(I[i]) and not isnan(I[i + 1]):
                p1 = x[i] * xscale + xoffset, I[i] * Iscale + Ioffset
                p2 = x[i + 1] * xscale + xoffset, I[i + 1] * Iscale + Ioffset
                lines += [(p1[0], p1[1], p2[0], p2[1])]
        dc.DrawLineList(lines)

        # Draw vertical profile at the left edge of the image.
        profile_color = wx.Colour(255, 0, 255)
        dc.SetPen(wx.Pen(profile_color, 1))
        y = xvals(yprofile)
        I = yvals(yprofile)
        Imax = max(I) if len(I) > 0 else nan
        if Imax == 0: Imax = 1
        Iscale = 0.35 * (ROI_xmax - ROI_xmin) * xscale / Imax
        Ioffset = ROI_xmin * xscale + xoffset
        lines = []
        for i in range(0, len(y) - 1):
            if not isnan(I[i]) and not isnan(I[i + 1]):
                p1 = I[i] * Iscale + Ioffset, y[i] * yscale + yoffset
                p2 = I[i + 1] * Iscale + Ioffset, y[i + 1] * yscale + yoffset
                lines += [(p1[0], p1[1], p2[0], p2[1])]
        dc.DrawLineList(lines)

        # Draw a box around the ROI.
        center_color = wx.Colour(128, 128, 255)
        dc.SetPen(wx.Pen(profile_color, 1))
        x1, y1 = ROI_xmin * xscale + xoffset, ROI_ymin * yscale + yoffset
        x2, y2 = ROI_xmax * xscale + xoffset - 1, ROI_ymax * yscale + yoffset - 1
        lines = [(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)]
        dc.DrawLines(lines)

        # Draw a box around center of the beam, with the size of the FWHM.
        FWHM_color = wx.Colour(255, 0, 0)
        dc.SetPen(wx.Pen(FWHM_color, 1))
        width, height = FWHM(xprofile), FWHM(yprofile)
        cx, cy = CFWHM(xprofile), CFWHM(yprofile)

        x1, y1 = (cx - width / 2) * xscale + xoffset, (
            cy - height / 2) * yscale + yoffset
        x2, y2 = (cx + width / 2) * xscale + xoffset, (
            cy + height / 2) * yscale + yoffset
        lines = [(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)]
        dc.DrawLines(lines)

        # Draw a vertical and horizontal line throught the center.
        center_color = wx.Colour(128, 128, 255)
        dc.SetPen(wx.Pen(center_color, 1))
        dc.DrawLines([(cx * xscale + xoffset, H), (cx * xscale + xoffset, 0)])
        dc.DrawLines([(0, cy * yscale + yoffset), (W, cy * yscale + yoffset)])

        # Annotate the lines.
        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetPointSize(10)
        dc.SetFont(font)
        dc.SetTextForeground(center_color)

        dx = cx - self.values["x_nominal"]
        if abs(dx) < 1: label = "%+.0f um" % (dx * 1000)
        else: label = "%+.3f mm" % dx
        x, y = cx * xscale + xoffset, 0.875 * H
        tw, th = dc.GetTextExtent(label)
        dc.DrawRotatedText(label, toint(x + 2), toint(y - th / 2), 0)

        dy = cy - self.values["y_nominal"]
        if abs(dy) < 1: label = "%+.0f um" % (dy * 1000)
        else: label = "%+.3f mm" % dy
        x, y = 0.175 * W, cy * yscale + yoffset
        tw, th = dc.GetTextExtent(label)
        dc.DrawRotatedText(label, toint(x - th / 2), toint(y + 2), -90)