Beispiel #1
0
 def update_roi(self):
     axes=(0,1)
     # self.line_data = self.line_roi.getArrayRegion(self.zdata, self.imageItem, axes=(0,1))
     img = self.imageItem
     imgPts = [self.line_roi.mapToItem(img, h['item'].pos()) for h in self.line_roi.handles]
     d = Point(imgPts[1] - imgPts[0])
     o = Point(imgPts[0])
     z = fn.affineSlice(self.zdata, shape=(int(d.length()),), vectors=[Point(d.norm())], origin=o, axes=axes, order=1)
     x = fn.affineSlice(self.xdata, shape=(int(d.length()),), vectors=[Point(d.norm())], origin=o, axes=axes, order=1)
     y = fn.affineSlice(self.ydata, shape=(int(d.length()),), vectors=[Point(d.norm())], origin=o, axes=axes, order=1)
     self.line_data = (x,y,z)
    def movePoint(self,
                  handle,
                  pos,
                  modifiers=QtCore.Qt.KeyboardModifier(),
                  finish=True,
                  coords='parent'):
        ## called by Handles when they are moved.
        ## pos is the new position of the handle in scene coords, as requested by the handle.

        newState = self.stateCopy()
        index = self.indexOfHandle(handle)
        h = self.handles[index]
        p0 = self.mapToParent(h['pos'] * self.state['size'])
        p1 = Point(pos)

        if coords == 'parent':
            pass
        elif coords == 'scene':
            p1 = self.mapSceneToParent(p1)
        else:
            raise Exception(
                "New point location must be given in either 'parent' or 'scene' coordinates."
            )

        ## transform p0 and p1 into parent's coordinates (same as scene coords if there is no parent). I forget why.
        #p0 = self.mapSceneToParent(p0)
        #p1 = self.mapSceneToParent(p1)

        ## Handles with a 'center' need to know their local position relative to the center point (lp0, lp1)
        if 'center' in h:
            c = h['center']
            cs = c * self.state['size']
            lp0 = self.mapFromParent(p0) - cs
            lp1 = self.mapFromParent(p1) - cs

        if h['type'] == 't':
            snap = True if (modifiers & QtCore.Qt.ControlModifier) else None
            #if self.translateSnap or ():
            #snap = Point(self.snapSize, self.snapSize)
            self.translate(p1 - p0, snap=snap, update=False)

        elif h['type'] == 'f':
            newPos = self.mapFromParent(p1)
            h['item'].setPos(newPos)
            h['pos'] = newPos
            self.freeHandleMoved = True
            #self.sigRegionChanged.emit(self)  ## should be taken care of by call to stateChanged()

        elif h['type'] == 's':
            ## If a handle and its center have the same x or y value, we can't scale across that axis.
            if h['center'][0] == h['pos'][0]:
                lp1[0] = 0
            if h['center'][1] == h['pos'][1]:
                lp1[1] = 0

            ## snap
            if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier):
                lp1[0] = round(lp1[0] / self.snapSize) * self.snapSize
                lp1[1] = round(lp1[1] / self.snapSize) * self.snapSize

            ## preserve aspect ratio (this can override snapping)
            if h['lockAspect'] or (modifiers & QtCore.Qt.AltModifier):
                #arv = Point(self.preMoveState['size']) -
                lp1 = lp1.proj(lp0)

            ## determine scale factors and new size of ROI
            hs = h['pos'] - c
            if hs[0] == 0:
                hs[0] = 1
            if hs[1] == 0:
                hs[1] = 1
            newSize = lp1 / hs

            ## Perform some corrections and limit checks
            if newSize[0] == 0:
                newSize[0] = newState['size'][0]
            if newSize[1] == 0:
                newSize[1] = newState['size'][1]
            if not self.invertible:
                if newSize[0] < 0:
                    newSize[0] = newState['size'][0]
                if newSize[1] < 0:
                    newSize[1] = newState['size'][1]
            if self.aspectLocked:
                newSize[0] = newSize[1]

            ## Move ROI so the center point occupies the same scene location after the scale
            s0 = c * self.state['size']
            s1 = c * newSize
            cc = self.mapToParent(s0 - s1) - self.mapToParent(Point(0, 0))

            ## update state, do more boundary checks
            newState['size'] = newSize
            newState['pos'] = newState['pos'] + cc

            if self.maxBounds is not None:
                r = self.stateRect(newState)
                if not self.maxBounds.contains(r):

                    #Order of bounds checking is important !
                    #1. Bound x and y first, update width and height
                    #if necessary
                    #2. Then bound height and width
                    target_x = newState['pos'][0]
                    target_y = newState['pos'][1]
                    target_width = newState['size'][0]
                    target_height = newState['size'][1]

                    #target x must be more than min_x but less than min__x
                    # + max_width
                    #update newState position values first
                    newState['pos'][0] = min(max(self.maxBounds.x(), target_x),
                                             self.maxBounds.right())
                    newState['pos'][1] = min(max(self.maxBounds.y(), target_y),
                                             self.maxBounds.bottom())

                    #Adjusts width and height to make sure right and bottom
                    #edges are the same despite new newState position values
                    target_width = (target_width + target_x -
                                    newState['pos'][0])
                    target_height = (target_height + target_y -
                                     newState['pos'][1])

                    #Apply bound checking for updated target widths
                    newState['size'][0] = min(
                        target_width,
                        self.maxBounds.right() - newState['pos'][0])

                    newState['size'][1] = min(
                        target_height,
                        self.maxBounds.bottom() - newState['pos'][1])
            """End of edit"""
            """Start of old code
                    return
            End of old code"""

            self.setPos(newState['pos'], update=False)
            self.setSize(newState['size'], update=False)

        elif h['type'] in ['r', 'rf']:
            if h['type'] == 'rf':
                self.freeHandleMoved = True

            if not self.rotateAllowed:
                return
            ## If the handle is directly over its center point, we can't compute an angle.
            try:
                if lp1.length() == 0 or lp0.length() == 0:
                    return
            except OverflowError:
                return

            ## determine new rotation angle, constrained if necessary
            ang = newState['angle'] - lp0.angle(lp1)
            if ang is None:  ## this should never appen..
                return
            if self.rotateSnap or (modifiers & QtCore.Qt.ControlModifier):
                ang = round(ang / 15.) * 15.  ## 180/12 = 15

            ## create rotation transform
            tr = QtGui.QTransform()
            tr.rotate(ang)

            ## move ROI so that center point remains stationary after rotate
            cc = self.mapToParent(cs) - (tr.map(cs) + self.state['pos'])
            newState['angle'] = ang
            newState['pos'] = newState['pos'] + cc

            ## check boundaries, update
            if self.maxBounds is not None:
                r = self.stateRect(newState)
                if not self.maxBounds.contains(r):
                    return
            #self.setTransform(tr)
            self.setPos(newState['pos'], update=False)
            self.setAngle(ang, update=False)
            #self.state = newState

            ## If this is a free-rotate handle, its distance from the center may change.

            if h['type'] == 'rf':
                h['item'].setPos(self.mapFromScene(
                    p1))  ## changes ROI coordinates of handle

        elif h['type'] == 'sr':
            if h['center'][0] == h['pos'][0]:
                scaleAxis = 1
                nonScaleAxis = 0
            else:
                scaleAxis = 0
                nonScaleAxis = 1

            try:
                if lp1.length() == 0 or lp0.length() == 0:
                    return
            except OverflowError:
                return

            ang = newState['angle'] - lp0.angle(lp1)
            if ang is None:
                return
            if self.rotateSnap or (modifiers & QtCore.Qt.ControlModifier):
                #ang = round(ang / (np.pi/12.)) * (np.pi/12.)
                ang = round(ang / 15.) * 15.

            hs = abs(h['pos'][scaleAxis] - c[scaleAxis])
            newState['size'][scaleAxis] = lp1.length() / hs
            #if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier):
            if self.scaleSnap:  ## use CTRL only for angular snap here.
                newState['size'][scaleAxis] = round(
                    newState['size'][scaleAxis] /
                    self.snapSize) * self.snapSize
            if newState['size'][scaleAxis] == 0:
                newState['size'][scaleAxis] = 1
            if self.aspectLocked:
                newState['size'][nonScaleAxis] = newState['size'][scaleAxis]

            c1 = c * newState['size']
            tr = QtGui.QTransform()
            tr.rotate(ang)

            cc = self.mapToParent(cs) - (tr.map(c1) + self.state['pos'])
            newState['angle'] = ang
            newState['pos'] = newState['pos'] + cc
            if self.maxBounds is not None:
                r = self.stateRect(newState)
                if not self.maxBounds.contains(r):
                    return
            #self.setTransform(tr)
            #self.setPos(newState['pos'], update=False)
            #self.prepareGeometryChange()
            #self.state = newState
            self.setState(newState, update=False)

        self.stateChanged(finish=finish)
    def scaleBy(self, s=None, center=None, x=None, y=None):

        if s is not None:
            scale = Point(s)
        else:
            scale = [x, y]

        affect = [True, True]
        if scale[0] is None and scale[1] is None:
            return
        elif scale[0] is None:
            affect[0] = False
            scale[0] = 1.0
        elif scale[1] is None:
            affect[1] = False
            scale[1] = 1.0

        scale = Point(scale)

        if self.state['aspectLocked'] is not False:

            scale[0] = scale[1]
        """Edit"""
        vr = self.viewRect()
        """End of Edit"""

        if center is None:
            center = Point(vr.center())
        else:
            center = Point(center)

        tl = center + (vr.topLeft() - center) * scale
        br = center + (vr.bottomRight() - center) * scale
        """Addition"""
        yMax = self.state['limits']['yLimits'][1]
        xMax = self.state['limits']['xLimits'][1]
        xMin = self.state['limits']['xLimits'][0]
        yMin = self.state['limits']['yLimits'][0]

        scale_limit = []
        if yMax is not None and affect[0]:

            if (br.y() > yMax):

                scale_limit.append((yMax - center.y()) /
                                   (1.0 * vr.bottomRight().y() - center.y()))
                print 'yMax scale is :' + str(scale_limit[-1])

        if xMax is not None:

            if (br.x() > xMax) and affect[1]:
                scale_limit.append((xMax - center.x()) /
                                   (1.0 * vr.bottomRight().x() - center.x()))
                print 'xMax scale is :' + str(scale_limit[-1])

        if xMin is not None:

            if (tl.x() < xMin) and affect[1]:
                scale_limit.append((xMin - center.x()) /
                                   (1.0 * vr.topLeft().x() - center.x()))
                print 'xMin scale is :' + str(scale_limit[-1])

        if yMin is not None:

            if (tl.y() < yMin) and affect[0]:
                scale_limit.append((yMin - center.y()) /
                                   (1.0 * vr.topLeft().y() - center.y()))
                print 'yMin scale is :' + str(scale_limit[-1])

        if self.state['aspectLocked'] is not False and len(scale_limit) > 0:

            min_scale_limit = min(scale_limit)

            scale[1] = min_scale_limit
            scale[0] = scale[1]

            tl = center + (vr.topLeft() - center) * scale
            br = center + (vr.bottomRight() - center) * scale
        """End of Addition"""

        if not affect[0]:
            self.setYRange(tl.y(), br.y(), padding=0)
        elif not affect[1]:
            self.setXRange(tl.x(), br.x(), padding=0)
        else:
            self.setRange(QtCore.QRectF(tl, br), padding=0)
Beispiel #4
0
view = w.addViewBox()
view.setAspectLocked()
#grid = pg.GridItem()
#view.addItem(grid)
view.setRange(pg.QtCore.QRectF(-50, -30, 100, 100))

optics = []
rays = []
m1 = Mirror(r1=-100, pos=(5, 0), d=5, angle=-15)
optics.append(m1)
m2 = Mirror(r1=-70, pos=(-40, 30), d=6, angle=180 - 15)
optics.append(m2)

allRays = []
for y in np.linspace(-10, 10, 21):
    r = Ray(start=Point(-100, y))
    view.addItem(r)
    allRays.append(r)

for o in optics:
    view.addItem(o)

t1 = Tracer(allRays, optics)

### Dispersion demo

optics = []

view = w.addViewBox()

view.setAspectLocked()
Beispiel #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
        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)
 def add_ctrl_pts(self, ctrl_pts):
     for (x, y) in ctrl_pts:
         self.ctrl_pts.append(Point(x, y))
     self._update_spline()
Beispiel #7
0
    def intersectRay(self, ray):
        ## return the point of intersection and the angle of incidence
        #print "intersect ray"
        h = self.h2
        r = self.r
        p, dir = ray.currentState(
            relativeTo=self)  # position and angle of ray in local coords.
        #print "  ray: ", p, dir
        p = p - Point(r, 0)  ## move position so center of circle is at 0,0
        #print "  adj: ", p, r

        if r == 0:
            #print "  flat"
            if dir[0] == 0:
                y = 0
            else:
                y = p[1] - p[0] * dir[1] / dir[0]
            if abs(y) > h:
                return None, None
            else:
                return (Point(0, y), np.arctan2(dir[1], dir[0]))
        else:
            #print "  curve"
            ## find intersection of circle and line (quadratic formula)
            dx = dir[0]
            dy = dir[1]
            dr = (dx**2 + dy**2)**0.5
            D = p[0] * (p[1] + dy) - (p[0] + dx) * p[1]
            idr2 = 1.0 / dr**2
            disc = r**2 * dr**2 - D**2
            if disc < 0:
                return None, None
            disc2 = disc**0.5
            if dy < 0:
                sgn = -1
            else:
                sgn = 1

            br = self.path.boundingRect()
            x1 = (D * dy + sgn * dx * disc2) * idr2
            y1 = (-D * dx + abs(dy) * disc2) * idr2
            if br.contains(x1 + r, y1):
                pt = Point(x1, y1)
            else:
                x2 = (D * dy - sgn * dx * disc2) * idr2
                y2 = (-D * dx - abs(dy) * disc2) * idr2
                pt = Point(x2, y2)
                if not br.contains(x2 + r, y2):
                    return None, None
                    raise Exception("No intersection!")

            norm = np.arctan2(pt[1], pt[0])
            if r < 0:
                norm += np.pi
            #print "  norm:", norm*180/3.1415
            dp = p - pt
            #print "  dp:", dp
            ang = np.arctan2(dp[1], dp[0])
            #print "  ang:", ang*180/3.1415
            #print "  ai:", (ang-norm)*180/3.1415

            #print "  intersection:", pt
            return pt + Point(r, 0), ang - norm
Beispiel #8
0
 def updateTransform(self):
     self.resetTransform()
     self.setPos(0, 0)
     self.translate(Point(self['pos']))
     self.rotate(self['angle'])