Example #1
0
    def getBackground(self):
        if self.background is None:
            w, h = self.params['sensorSize']

            tr = self.globalTransform()
            tr = pg.SRTTransform(tr)
            m = QtGui.QTransform()
            m.scale(3e6, 3e6)
            m.translate(0.0005, 0.0005)
            tr = tr * m

            origin = tr.map(pg.Point(0, 0))
            x = (tr.map(pg.Point(1, 0)) - origin)
            y = (tr.map(pg.Point(0, 1)) - origin)
            origin = np.array([origin.x(), origin.y()])
            x = np.array([x.x(), x.y()])
            y = np.array([y.x(), y.y()])

            ## slice fractal from pre-rendered data
            vectors = (x, y)
            self.background = pg.affineSlice(self.bgData, (w, h),
                                             origin,
                                             vectors, (0, 1),
                                             order=1)

        return self.background
Example #2
0
    def newFrames(self):
        """Return a list of all frames acquired since the last call to newFrames."""
        now = ptime.time()

        dt = now - self.lastFrameTime
        exp = self.getParam('exposure')
        bin = self.getParam('binning')
        fps = 1.0 / (exp + (40e-3 / (bin[0] * bin[1])))
        nf = int(dt * fps)
        if nf == 0:
            return []

        region = self.getParam('region')
        bg = self.getBackground()[region[0]:region[0] + region[2],
                                  region[1]:region[1] + region[3]]

        ## update cells
        spikes = np.random.poisson(min(dt, 0.4) * self.cells['rate'])
        self.cells['value'] *= np.exp(-dt / self.cells['decayTau'])
        self.cells['value'] = np.clip(self.cells['value'] + spikes * 0.2, 0, 1)
        shape = region[2:]
        self.lastFrameTime = now + exp
        data = self.getNoise(shape)
        data[data < 0] = 0

        data += bg * (exp * 1000)

        ## draw cells
        px = (self.pixelVectors()[0]**2).sum()**0.5

        ## Generate transform that maps grom global coordinates to image coordinates
        cameraTr = pg.SRTTransform3D(self.inverseGlobalTransform())
        # note we use binning=(1,1) here because the image is downsampled later.
        frameTr = self.makeFrameTransform(region, [1, 1]).inverted()[0]
        tr = pg.SRTTransform(frameTr * cameraTr)

        for cell in self.cells:
            w = cell['size'] / px
            pos = pg.Point(cell['x'], cell['y'])
            imgPos = tr.map(pos)
            start = (int(imgPos.x()), int(imgPos.y()))
            stop = (int(start[0] + w), int(start[1] + w))
            val = cell['intensity'] * cell['value'] * self.getParam('exposure')
            data[max(0, start[0]):max(0, stop[0]),
                 max(0, start[1]):max(0, stop[1])] += val

        data = fn.downsample(data, bin[0], axis=0)
        data = fn.downsample(data, bin[1], axis=1)
        data = data.astype(np.uint16)

        self.frameId += 1
        frames = []
        for i in range(nf):
            frames.append({
                'data': data,
                'time': now + (i / fps),
                'id': self.frameId
            })
        return frames
Example #3
0
 def globalTransformChanged(self, emitter=None, changedDev=None, transform=None):
     ## scope has moved; update viewport and camera outlines.
     ## This is only used when the camera is not running--
     ## if the camera is running, then this is taken care of in drawFrame to
     ## ensure that the image remains stationary on screen.
     if not self.cam.isRunning():
         tr = pg.SRTTransform(self.cam.globalTransform())
         self.updateTransform(tr)
Example #4
0
    def updateCameraDecorations(self):
        ps = self.cameraScale
        pos = self.lastCameraPosition
        cs = self.camSize
        if ps is None:
            return

        m = self.cam.globalTransform()
        self.cameraItemGroup.setTransform(pg.SRTTransform(m))
Example #5
0
    def imageUpdated(self, frame):
        ## New image is displayed; update image transform
        self.imageItem.setTransform(frame.frameTransform().as2D())

        ## Update viewport to correct for scope movement/scaling
        tr = pg.SRTTransform(frame.deviceTransform())
        self.updateTransform(tr)

        self.imageItemGroup.setTransform(tr)
Example #6
0
 def ifaceTransformChanged(self, iface):
     # imaging device moved; update viewport and tracked group.
     # This is only used when the camera is not running--
     # if the camera is running, then this is taken care of in drawFrame to
     # ensure that the image remains stationary on screen.
     prof = Profiler()
     if not self.cam.isRunning():
         tr = pg.SRTTransform(self.cam.globalTransform())
         self.updateTransform(tr)
Example #7
0
    def __init__(self, image=None, **opts):

        ## If no image was specified, check for a file handle..
        if image is None:
            image = opts.get('handle', None)

        item = None
        self.data = None

        if isinstance(image, QtGui.QGraphicsItem):
            item = image
        elif isinstance(image, np.ndarray):
            self.data = image
        elif isinstance(image, DataManager.FileHandle):
            opts['handle'] = image
            self.handle = image
            self.data = self.handle.read()

            if 'name' not in opts:
                opts['name'] = self.handle.shortName()

            try:
                if 'transform' in self.handle.info():
                    tr = pg.SRTTransform3D(self.handle.info()['transform'])
                    tr = pg.SRTTransform(tr)  ## convert to 2D
                    opts['pos'] = tr.getTranslation()
                    opts['scale'] = tr.getScale()
                    opts['angle'] = tr.getRotation()
                else:  ## check for older info formats
                    if 'imagePosition' in self.handle.info():
                        opts['scale'] = self.handle.info()['pixelSize']
                        opts['pos'] = self.handle.info()['imagePosition']
                    elif 'Downsample' in self.handle.info():
                        ### Needed to support an older format stored by 2p imager
                        if 'pixelSize' in self.handle.info():
                            opts['scale'] = self.handle.info()['pixelSize']
                        if 'microscope' in self.handle.info():
                            m = self.handle.info()['microscope']
                            opts['pos'] = m['position'][0:2]
                        else:
                            info = self.data._info[-1]
                            opts['pos'] = info.get('imagePosition', None)
                    elif hasattr(self.data, '_info'):
                        info = self.data._info[-1]
                        opts['scale'] = info.get('pixelSize', None)
                        opts['pos'] = info.get('imagePosition', None)
                    else:
                        opts['defaultUserTransform'] = {'scale': (1e-5, 1e-5)}
                        opts['scalable'] = True
            except:
                debug.printExc(
                    'Error reading transformation for image file %s:' %
                    image.name())

        if item is None:
            item = pg.ImageItem()
        CanvasItem.__init__(self, item, **opts)

        self.splitter = QtGui.QSplitter()
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.layout.addWidget(self.splitter, self.layout.rowCount(), 0, 1, 2)

        self.filterGroup = pg.GroupBox("Image Filter")
        fgl = QtGui.QGridLayout()
        fgl.setContentsMargins(3, 3, 3, 3)
        fgl.setSpacing(1)
        self.filterGroup.setLayout(fgl)
        self.filter = ImageFilterWidget()
        self.filter.sigStateChanged.connect(self.filterStateChanged)
        fgl.addWidget(self.filter)
        self.splitter.addWidget(self.filterGroup)

        self.histogram = pg.HistogramLUTWidget()
        self.histogram.setImageItem(self.graphicsItem())

        # addWidget arguments: row, column, rowspan, colspan
        self.splitter.addWidget(self.histogram)

        self.imgModeCombo = QtGui.QComboBox()
        self.imgModeCombo.addItems(
            ['SourceOver', 'Overlay', 'Plus', 'Multiply'])
        self.layout.addWidget(self.imgModeCombo, self.layout.rowCount(), 0, 1,
                              1)
        self.imgModeCombo.currentIndexChanged.connect(self.imgModeChanged)

        self.autoBtn = QtGui.QPushButton("Auto")
        self.autoBtn.setCheckable(True)
        self.autoBtn.setChecked(True)
        self.layout.addWidget(self.autoBtn,
                              self.layout.rowCount() - 1, 1, 1, 1)

        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.layout.addWidget(self.timeSlider, self.layout.rowCount(), 0, 1, 2)
        self.timeSlider.valueChanged.connect(self.timeChanged)

        # ## controls that only appear if there is a time axis
        self.timeControls = [self.timeSlider]

        if self.data is not None:
            if isinstance(self.data, pg.metaarray.MetaArray):
                self.filter.setInput(self.data.asarray())
            else:
                self.filter.setInput(self.data)
            self.updateImage()

            # Needed to ensure selection box wraps the image properly
            tr = self.saveTransform()
            self.resetUserTransform()
            self.restoreTransform(tr)
Example #8
0
    def runCalibration(self):
        """The scanner calibration routine:
            1) Measure background frame, then scan mirrors 
               while collecting frames as fast as possible (self.scan())
            2) Locate spot in every frame using gaussian fit
            3) Map image spot locations to coordinate system of Scanner device's parent
            3) Do parabolic fit to determine mapping between voltage and position
        """
        camera = str(self.ui.cameraCombo.currentText())
        laser = str(self.ui.laserCombo.currentText())
        blurRadius = 5
        
        ## Do fast scan of entire allowed command range
        (background, cameraResult, positions) = self.scan()
        #self.calibrationResult = {'bg': background, 'frames': cameraResult, 'pos': positions}

        with pg.ProgressDialog("Calibrating scanner: Computing spot positions...", 0, 100) as dlg:
            dlg.show()
            dlg.raise_()  # Not sure why this is needed here..

            ## Forget first 2 frames since some cameras can't seem to get these right.
            frames = cameraResult.asArray()
            frames = frames[2:]
            positions = positions[2:]
            
            ## Do background subtraction
            ## take out half the data until it can do the calculation without having a MemoryError.
            finished = False
            gc.collect()
            while not finished:
                try:
                    frames = frames.astype(np.float32)
                    frames -= background.astype(np.float32)
                    finished=True
                except MemoryError:
                    frames = frames[::2,:,:]
                    positions = positions[::2]
                    finished = False
                
            ## Find a frame with a spot close to the center (within center 1/3)
            cx = frames.shape[1] / 3
            cy = frames.shape[2] / 3
            centerSlice = blur(frames[:, cx:cx*2, cy:cy*2], (0, 5, 5)).max(axis=1).max(axis=1)
            maxIndex = argmax(centerSlice)
            maxFrame = frames[maxIndex]
            dlg.setValue(5)

            ## Determine spot intensity and width
            mfBlur = blur(maxFrame, blurRadius)
            amp = mfBlur.max() - median(mfBlur)  ## guess intensity of spot
            (x, y) = argwhere(mfBlur == mfBlur.max())[0]   ## guess location of spot
            fit = fitGaussian2D(maxFrame, [amp, x, y, maxFrame.shape[0] / 10, 0.])[0]  ## gaussian fit to locate spot exactly
            # convert sigma to full width at 1/e
            fit[3] = abs(2 * (2 ** 0.5) * fit[3]) ## sometimes the fit for width comes out negative. *shrug*
            someFrame = cameraResult.frames()[0]
            frameTransform = pg.SRTTransform(someFrame.globalTransform())
            pixelSize = someFrame.info()['pixelSize'][0]
            spotAmplitude = fit[0]
            spotWidth = abs(fit[3] * pixelSize)
            size = self.spotSize(mfBlur)
            dlg.setValue(50)

            ## Determine location of spot within each frame, 
            ## ignoring frames where the spot is too dim or too close to the frame edge
            spotLocations = []
            globalSpotLocations = []
            spotCommands = []
            spotFrames = []
            margin = fit[3]
            
            for i in range(len(positions)):
                dlg.setValue(50. + 50. * i / frames.shape[0])
                if dlg.wasCanceled():
                    raise HelpfulException('Calibration canceled by user.', msgType='warning')

                frame = frames[i]
                fBlur = blur(frame.astype(np.float32), blurRadius)
    
                mx = fBlur.max()
                diff = mx - fBlur.min()
                ss = self.spotSize(fBlur)
                if ss < size * 0.6:
                    #print "Ignoring spot:", ss
                    continue
                #else:
                    #print "Keeping spot:", ss
                    
                (x, y) = argwhere(fBlur == mx)[0]   # guess location of spot
                if x < margin or x > frame.shape[0] - margin:
                    #print "   ..skipping; too close to edge", x, y
                    continue
                if y < margin or y > frame.shape[1] - margin:
                    #print "   ..skipping; too close to edge", x, y
                    continue
                
                frame[x,y] = -1  ## mark location of peak in image
                
                ## convert pixel location to coordinate system of scanner's parent
                globalPos = frameTransform.map(pg.Point(x, y))  ## Map from frame pixel location to global coordinates
                localPos = self.dev.mapGlobalToParent(globalPos)  ## map from global to parent coordinate system. This is the position we calibrate to.
                #print (x, y), (globalPos.x(), globalPos.y()), (localPos.x(), localPos.y())
                
                spotLocations.append([localPos.x(), localPos.y()])
                globalSpotLocations.append([globalPos.x(), globalPos.y()])
                spotCommands.append(positions[i])
                spotFrames.append(frame[newaxis])
        
        ## sanity check on spot frame
        if len(spotFrames) == 0:
            self.ui.view.setImage(frames)
            raise HelpfulException('Calibration never detected laser spot!  Looking for spots that are %f pixels wide.'% fit[3], reasons=['shutter is disabled', 'mirrors are disabled', 'objective is not clean', 'spot is not visible or not bright enough when shutter is open'])

        spotFrameMax = concatenate(spotFrames).max(axis=0)
        self.ui.view.setImage(spotFrameMax, transform=frameTransform)
        
        self.clearSpots()
        for sl in globalSpotLocations:
            #self.addSpot(sl, fit[3]*binning[0])
            self.addSpot(sl, spotWidth)
        self.ui.view.autoRange()
        
        if len(spotFrames) < 10:
            raise HelpfulException('Calibration detected only %d frames with laser spot; need minimum of 10.' % len(spotFrames), reasons=['spot is too dim for camera sensitivity', 'objective is not clean', 'mirrors are scanning too quickly', 'mirror scanning region is not within the camera\'s view'])
        
        ## Fit all data to a map function
        mapParams = self.generateMap(array(spotLocations), array(spotCommands))
        #print 
        #print "Map parameters:", mapParams
        
        if spotWidth < 0:
            raise Exception()
        return (mapParams, (spotAmplitude, spotWidth))
Example #9
0
    def getBackground(self):
        if self.background is None:
            w, h = self.params['sensorSize']
            tr = self.globalTransform()

            if isinstance(self.bgData, dict):
                # select data based on objective
                obj = self.getObjective()
                data = self.bgData[obj]
                info = self.bgInfo[obj]
                px = info['pixelSize']
                pz = info['depths'][1] - info['depths'][0]

                m = pg.QtGui.QMatrix4x4()
                pos = info['transform']['pos']
                m.scale(1 / px[0], 1 / px[1], 1 / pz)
                m.translate(-pos[0], -pos[1], -info['depths'][0])

                tr2 = m * tr
                origin = tr2.map(pg.Vector(0, 0, 0))
                #print(origin)
                origin = [int(origin.x()), int(origin.y()), origin.z()]

                ## slice data
                camRect = QtCore.QRect(origin[0], origin[1], w, h)
                dataRect = QtCore.QRect(0, 0, data.shape[1], data.shape[2])
                overlap = camRect.intersected(dataRect)
                tl = overlap.topLeft() - camRect.topLeft()

                z = origin[2]
                z1 = np.floor(z)
                z2 = np.ceil(z)
                s = (z - z1) / (z2 - z1)
                z1 = int(np.clip(z1, 0, data.shape[0] - 1))
                z2 = int(np.clip(z2, 0, data.shape[0] - 1))
                src1 = data[z1,
                            overlap.left():overlap.left() + overlap.width(),
                            overlap.top():overlap.top() + overlap.height()]
                src2 = data[z2,
                            overlap.left():overlap.left() + overlap.width(),
                            overlap.top():overlap.top() + overlap.height()]
                src = src1 * (1 - s) + src2 * s

                bg = np.empty((w, h), dtype=data.dtype)
                bg[:] = 100
                bg[tl.x():tl.x() + overlap.width(),
                   tl.y():tl.y() + overlap.height()] = src
                self.background = bg
                #vectors = ([1, 0, 0], [0, 1, 0])
                #self.background = pg.affineSlice(data, (w,h), origin, vectors, (1, 2, 0), order=1)
            else:
                tr = pg.SRTTransform(tr)
                m = QtGui.QTransform()

                m.scale(3e6, 3e6)
                m.translate(0.0005, 0.0005)
                tr = tr * m

                origin = tr.map(pg.Point(0, 0))
                x = (tr.map(pg.Point(1, 0)) - origin)
                y = (tr.map(pg.Point(0, 1)) - origin)
                origin = np.array([origin.x(), origin.y()])
                x = np.array([x.x(), x.y()])
                y = np.array([y.x(), y.y()])

                ## slice fractal from pre-rendered data
                vectors = (x, y)
                self.background = pg.affineSlice(self.bgData, (w, h),
                                                 origin,
                                                 vectors, (0, 1),
                                                 order=1)

        return self.background
Example #10
0
def show(dh=None):
    """
    Display a graphic of the currently selected slice / cell
    """
    
    global v, g, atlas
    if dh is None:
        dh = man.currentFile
    v.clear()
    
    if 'cell' in dh.shortName().lower():
        cd = dh
        sd = cd.parent()
    else:
        sd = dh
        cd = None
    atlas.loadState(sd)
    g = atlas.schematicGraphicsItems()
    v.addItem(g)
    
    if cd is not None:
        ## small image to go over slice schematic
        imgf = cd['morphology.png']
        imgd = pg.colorToAlpha(imgf.read(), np.array([255,255,255]))
        mimg1 = pg.ImageItem(imgd)
        tr = pg.SRTTransform(imgf.info()['userTransform'])
        mimg1.setTransform(tr)
        mimg1.setParentItem(g.sliceGroup)
        g.cellImg1 = mimg1
        
        ## larger image to be displayed above
        cellGroup = pg.ItemGroup()
        g.cellGroup = cellGroup
        mimg2 = pg.ImageItem(imgd)
        mimg2.setParentItem(cellGroup)
        mimg2.setTransform(tr * g.sliceGroup.transform())
        mimg2.scale(1.0 / g.sliceScaleFactor, 1.0 / g.sliceScaleFactor)
        #angle = pg.SRTTransform(g.sliceGroup.transform()).getRotation()
        #mimg2.rotate(angle)
        cellScale = 50.
        cellGroup.scale(cellScale, cellScale)
        g.cellImg2 = mimg2
        
        ## reposition image above slice schematic
        b1 = g.atlasGroup.mapRectToParent(g.atlasGroup.childrenBoundingRect())
        b2 = g.sliceClip.mapRectToParent(g.sliceClip.boundingRect())
        bounds = b1 | b2
        cellGroup.setParentItem(g)
        imgBounds = g.mapRectFromItem(mimg2, mimg2.boundingRect())
        pos = pg.Point(bounds.center().x() - imgBounds.center().x(), bounds.top()-imgBounds.bottom()) 
        cellGroup.setPos(pos)
        
        ## add scale bar
        sbLength = 25e-6
        g.cellScale = Qt.QGraphicsLineItem(0.0, 0.0, sbLength, 0.0)
        g.cellScale.setPen(pg.mkPen(color=0.0, width=100e-6/cellScale, cosmetic=False))
        g.cellScale.setParentItem(cellGroup)
        g.cellScale.setZValue(10)
        g.cellScale.text = pg.TextItem(u"25 µm", anchor=(0.5, 1), color=(0,0,0))
        g.cellScale.text.setParentItem(g.cellScale)
        g.cellScale.text.setPos(sbLength*0.5, -50e-6/cellScale)
        corner = mimg2.mapToParent(mimg2.boundingRect()).boundingRect().bottomRight()
        g.cellScale.setPos(corner + pg.Point(-sbLength/2., -sbLength/3.))
        
        cell = dh
        sl = cell.parent()
        day = sl.parent()
        name = day.shortName() + "_" + sl.shortName() + "_" + cell.shortName()
        g.cellName = pg.TextItem(name, color=(0,0,0))
        g.cellName.setParentItem(cellGroup)
        g.cellName.setPos(corner + pg.Point(-sbLength*4,-sbLength/4.))
Example #11
0
def showMap(dh=None):
    """
    Display a graphic of an input map for the currently selected cell
    """
    
    global v, g, atlas
    if dh is None:
        dh = man.currentFile
    db = man.getModule('Data Manager').currentDatabase()
    v.clear()
    
    cd = dh
    sd = cd.parent()
    atlas.loadState(sd)
    
    g = atlas.schematicGraphicsItems(contours=False, sliceScale=10, cellDir=cd)
    v.addItem(g)
    
    cellGroup = pg.ItemGroup()
    g.cellGroup = cellGroup
    cellScale = 10.
    cellGroup.scale(cellScale, cellScale)
    cellGroup.setParentItem(g)
    
    g.atlasScale.hide()
    g.arrowGroup.hide()
    
    ## reposition/rescale atlas group
    b1 = g.atlasGroup.mapRectToParent(g.atlasGroup.childrenBoundingRect())
    b2 = g.sliceClip.mapRectToParent(g.sliceClip.boundingRect())
    g.atlasGroup.setPos(b2.right()-b1.left()+0.001, b2.top()-b1.top())
    
    b1 = g.atlasGroup.mapRectToParent(g.atlasGroup.childrenBoundingRect())    
    bounds = b1 | b2
    
    if cd.exists('morphology.png'):
        ## small image to go over slice schematic
        imgf = cd['morphology.png']
        imgd = pg.colorToAlpha(imgf.read(), np.array([255,255,255]))
        mimg1 = pg.ImageItem(imgd)
        tr = pg.SRTTransform(imgf.info()['userTransform'])
        mimg1.setTransform(tr)
        mimg1.setParentItem(g.sliceGroup)
        mimg1.setZValue(100)
        g.cellImg1 = mimg1
        
        ## larger image to be displayed above
        mimg2 = pg.ImageItem(imgd)
        mimg2.setParentItem(cellGroup)
        mimg2.setTransform(tr * g.sliceGroup.transform())
        mimg2.scale(1.0 / g.sliceScaleFactor, 1.0 / g.sliceScaleFactor)
        #angle = pg.SRTTransform(g.sliceGroup.transform()).getRotation()
        #mimg2.rotate(angle)
        g.cellImg2 = mimg2
        cellGroup.scale(5,5)
        
        ## reposition next to slice schematic
        imgBounds = g.mapRectFromItem(mimg2, mimg2.boundingRect())
        pos = pg.Point(bounds.right()-imgBounds.left(), bounds.bottom()-imgBounds.bottom()) 
        cellGroup.setPos(pos)
    
        ## add scale bar
        sbLength = 50e-6
        g.cellScale = Qt.QGraphicsLineItem(0.0, 0.0, sbLength, 0.0)
        g.cellScale.setPen(pg.mkPen(color=0.0, width=5))
        g.cellScale.setZValue(10)
        g.cellScale.text = pg.TextItem(u"%d µm" % int(sbLength*1e6), anchor=(0.5, 1), color=(0,0,0))
        g.cellScale.text.setParentItem(g.cellScale)
        g.cellScale.text.setPos(sbLength*0.5, -50e-6/cellScale)
        #g.cellScale = pg.ScaleBar(sbLength)
        g.cellScale.setParentItem(cellGroup)
        corner = mimg2.mapToParent(mimg2.boundingRect()).boundingRect().bottomRight()
        g.cellScale.setPos(corner + pg.Point(-sbLength/2., -sbLength/3.))
    pos = pg.SRTTransform(cd.info()['userTransform']).map(pg.Point(0,0))
    size = pg.Point(30e-6, 30e-6)
    g.cellMarker = Qt.QGraphicsEllipseItem(Qt.QRectF(pos-size, pos+size))
    g.cellMarker.setBrush(pg.mkBrush(100,100,255,150))
    g.cellMarker.setPen(pg.mkPen('k', width=0.5))
    g.cellMarker.setParentItem(g.sliceGroup)
    g.cellMarker.setZValue(90)
        
    sites = db.select('map_site_view', ['ProtocolDir', 'HasInput'], where={'CellDir': cd})
    if len(sites) > 0:
        tr = sites[0]['ProtocolDir'].parent().info().get('userTransform', None)
        if tr is None:
            tr = pg.SRTTransform()
        else:
            tr = pg.SRTTransform(tr)
            
        pos = []
        size = sites[0]['ProtocolDir'].info()['Scanner']['spotSize']
        brushes = []
        for site in sites:
            pd = site['ProtocolDir']
            x,y = pd.info()['Scanner']['position']
            p2 = tr.map(pg.Point(x,y))
            pos.append((p2.x(), p2.y()))
            if site['HasInput']:
                brushes.append(pg.mkBrush('w'))
            else:
                brushes.append(pg.mkBrush(None))
        inputMap = pg.ScatterPlotItem(pos=np.array(pos), size=size, brush=brushes, pen=(0,0,0,50), pxMode=False, antialias=True)
        g.sliceGroup.addItem(inputMap)
        g.inputMap = inputMap
        inputMap.setZValue(50)
    
    
    cell = dh
    sl = cell.parent()
    day = sl.parent()
    name = day.shortName() + "_" + sl.shortName() + "_" + cell.shortName()
    rec = db.select('DirTable_Cell', '*', where={'Dir': cd})[0]
    
    name += "\nType: " + str(rec['CellType']) + "   Temp: " + str(rec['Temperature']) + "   Internal: " + str(rec['Internal']) + "   Age:" + str(rec['Age']) + "   Raccess: " + str(rec['AccessResistance'])
    name += "\nDirect Area: %s>0pA %s>20pA %s>100pA" % (str(rec['DirectAreaGt0']), str(rec['DirectAreaGt20']), str(rec['DirectAreaGt100']))
    name += "   Direct n spikes: " + str(rec['DirectNSpikes'])
    name += "\nSpont Ex Decay: %s   Spont In Decay: %s" % (str(rec['SpontExDecay1']), str(rec['SpontInDecay']))
    name += "\nExcitatory input" if (rec['EvokedExDecay'] is not None or rec['EvokedExAmp'] is not None) else ""
    print(rec)
    #name += '\nDirect Slow Decay: %s %s' % (str(rec['DirectAreaGT0']), str(rec['DirectAreaGT0']))
    
    
    
    g.cellName = pg.TextItem(name, color=(0,0,0))
    g.cellName.setParentItem(g)
    g.cellName.setPos(0, bounds.bottom())
Example #12
0
 def subdevTransformChanged(self, sender, device, subdev):
     tr = pg.SRTTransform(device.deviceTransform(subdev))
     #print "subdevTransformChanged:", sender, device, subdev
     for item in self.groups[device][subdev]:
         item.setTransform(tr)
Example #13
0
 def transformChanged(self, sender, device):
     for subdev, items in self.groups[device].iteritems():
         tr = pg.SRTTransform(device.deviceTransform(subdev))
         for item in items:
             item.setTransform(tr)
Example #14
0
 def makeGroup(self, dev, subdev):
     """Construct a QGraphicsItemGroup for the specified device/subdevice.
     This is a good method to extend in subclasses."""
     newGroup = QtGui.QGraphicsItemGroup()
     newGroup.setTransform(pg.SRTTransform(dev.deviceTransform(subdev)))
     return newGroup
Example #15
0
    def storeToDB(self):
        ## collect list of cells and scans under this slice,
        ## read all positions with userTransform corrections
        prof = Profiler("Atlas.storeToDB", disabled=True)
        loaded = self.host.getLoadedFiles()
        cells = []
        prots = []
        for f in loaded:
            if not f.isDir() or not f.isGrandchildOf(self.sliceDir):
                continue
            if self.dataModel.dirType(f) == 'Cell':
                info = f.info()
                if 'userTransform' not in info:
                    continue
                cells.append((f, info['userTransform']['pos']))
            elif self.dataModel.dirType(f) == 'Protocol':
                info = f.info()
                scanInfo = info.get('Scanner', None)
                if scanInfo is None:
                    continue
                tr = pg.SRTTransform(info.get('userTransform', None))
                pos = tr.map(*scanInfo['position'])
                prots.append((f, pos))
            elif self.dataModel.dirType(f) == 'ProtocolSequence':
                info = f.info()
                tr = pg.SRTTransform(info.get('userTransform', None))
                for subName in f.subDirs():
                    subf = f[subName]
                    scanInfo = subf.info().get('Scanner', None)
                    if scanInfo is None:
                        continue
                    pos = tr.map(*scanInfo['position'])
                    prots.append((subf, pos))

        prof.mark("made list of positions")

        for ident, dirType, positions in [('_cell', 'Cell', cells),
                                          ('_protocol', 'Protocol', prots)]:

            ## map positions, build data tables
            data, fields = self.generateDataArray(positions, dirType)
            prof.mark("got data arrays for %s" % dirType)
            #dirColumn = dirType + 'Dir'
            #data = np.empty(len(positions), dtype=[('SliceDir', object), (dirColumn, object), ('right', float), ('anterior', float), ('dorsal', float)])

            #for i in range(len(positions)):
            #dh, pos = positions[i]
            #mapped = self.atlas.mapToAtlas(pg.Point(pos))
            ##print dh, pos
            ##print "  right:", mapped.x()
            ##print "  anter:", mapped.y()
            ##print "  dorsl:", mapped.z()
            #data[i] = (self.sliceDir, dh, mapped.x(), mapped.y(), mapped.z())

            ## write to DB
            db = self.ui.dbWidget.getDb()
            prof.mark('got db')
            table = self.ui.dbWidget.getTableName(self.atlas.DBIdentity +
                                                  ident)
            prof.mark('got table')

            #fields = collections.OrderedDict([
            #('SliceDir', 'directory:Slice'),
            #(dirColumn, 'directory:'+dirType),
            #('right', 'real'),
            #('anterior', 'real'),
            #('dorsal', 'real'),
            #])

            ## Make sure target table exists and has correct columns
            db.checkTable(table,
                          owner=self.atlas.DBIdentity + ident,
                          columns=fields,
                          create=True)
            prof.mark('checked table')

            ## delete old -- This is the slow part!
            old = db.select(table,
                            where={'SliceDir': self.sliceDir},
                            toArray=True)
            if old is not None:  ## only do deleting if there is already data stored for this slice -- try to speed things up
                for source in set(data[dirType + 'Dir']):
                    if source in old[
                            dirType +
                            'Dir']:  ## check that source is in the old data before we delete it - try to speed things up
                        db.delete(table, where={dirType + 'Dir': source})
            prof.mark('deleted old data')

            ## write new
            db.insert(table, data)
            prof.mark("added %s data to db" % dirType)

        prof.finish()
Example #16
0
    def __init__(self, image=None, **opts):
        """
        CanvasItem displaying an image. 
        The image may be 2 or 3-dimensional.
        Options:
            image: May be a fileHandle, ndarray, or GraphicsItem.
            handle: May optionally be specified in place of image

        """

        ## If no image was specified, check for a file handle..
        if image is None:
            image = opts.get('handle', None)

        item = None
        self.data = None
        self.currentT = None

        if isinstance(image, QtGui.QGraphicsItem):
            item = image
        elif isinstance(image, np.ndarray):
            self.data = image
        elif isinstance(image, DataManager.FileHandle):
            opts['handle'] = image
            self.handle = image
            self.data = self.handle.read()

            if 'name' not in opts:
                opts['name'] = self.handle.shortName()

            try:
                if 'transform' in self.handle.info():
                    tr = pg.SRTTransform3D(self.handle.info()['transform'])
                    tr = pg.SRTTransform(tr)  ## convert to 2D
                    opts['pos'] = tr.getTranslation()
                    opts['scale'] = tr.getScale()
                    opts['angle'] = tr.getRotation()
                else:  ## check for older info formats
                    if 'imagePosition' in self.handle.info():
                        opts['scale'] = self.handle.info()['pixelSize']
                        opts['pos'] = self.handle.info()['imagePosition']
                    elif 'Downsample' in self.handle.info():
                        ### Needed to support an older format stored by 2p imager
                        if 'pixelSize' in self.handle.info():
                            opts['scale'] = self.handle.info()['pixelSize']
                        if 'microscope' in self.handle.info():
                            m = self.handle.info()['microscope']
                            print 'm: ', m
                            print 'mpos: ', m['position']
                            opts['pos'] = m['position'][0:2]
                        else:
                            info = self.data._info[-1]
                            opts['pos'] = info.get('imagePosition', None)
                    elif hasattr(self.data, '_info'):
                        info = self.data._info[-1]
                        opts['scale'] = info.get('pixelSize', None)
                        opts['pos'] = info.get('imagePosition', None)
                    else:
                        opts['defaultUserTransform'] = {'scale': (1e-5, 1e-5)}
                        opts['scalable'] = True
            except:
                debug.printExc(
                    'Error reading transformation for image file %s:' %
                    image.name())

        if item is None:
            item = pg.ImageItem()
        CanvasItem.__init__(self, item, **opts)

        self.histogram = pg.PlotWidget()
        self.blockHistogram = False
        self.histogram.setMaximumHeight(100)
        self.levelRgn = pg.LinearRegionItem()
        self.histogram.addItem(self.levelRgn)
        self.updateHistogram(autoLevels=True)

        # addWidget arguments: row, column, rowspan, colspan
        self.layout.addWidget(self.histogram, self.layout.rowCount(), 0, 1, 3)

        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
        #self.timeSlider.setMinimum(0)
        #self.timeSlider.setMaximum(self.data.shape[0]-1)
        self.layout.addWidget(self.timeSlider, self.layout.rowCount(), 0, 1, 3)
        self.timeSlider.valueChanged.connect(self.timeChanged)
        self.timeSlider.sliderPressed.connect(self.timeSliderPressed)
        self.timeSlider.sliderReleased.connect(self.timeSliderReleased)
        thisRow = self.layout.rowCount()

        self.edgeBtn = QtGui.QPushButton('Edge')
        self.edgeBtn.clicked.connect(self.edgeClicked)
        self.layout.addWidget(self.edgeBtn, thisRow, 0, 1, 1)

        self.meanBtn = QtGui.QPushButton('Mean')
        self.meanBtn.clicked.connect(self.meanClicked)
        self.layout.addWidget(self.meanBtn, thisRow + 1, 0, 1, 1)

        self.tvBtn = QtGui.QPushButton('tv denoise')
        self.tvBtn.clicked.connect(self.tvClicked)
        self.layout.addWidget(self.tvBtn, thisRow + 2, 0, 1, 1)

        self.maxBtn = QtGui.QPushButton('Max no Filter')
        self.maxBtn.clicked.connect(self.maxClicked)
        self.layout.addWidget(self.maxBtn, thisRow, 1, 1, 1)

        self.maxBtn2 = QtGui.QPushButton('Max w/Gaussian')
        self.maxBtn2.clicked.connect(self.max2Clicked)
        self.layout.addWidget(self.maxBtn2, thisRow + 1, 1, 1, 1)

        self.maxMedianBtn = QtGui.QPushButton('Max w/Median')
        self.maxMedianBtn.clicked.connect(self.maxMedianClicked)
        self.layout.addWidget(self.maxMedianBtn, thisRow + 2, 1, 1, 1)

        self.filterOrder = QtGui.QComboBox()
        self.filterLabel = QtGui.QLabel('Order')
        for n in range(1, 11):
            self.filterOrder.addItem("%d" % n)
        self.layout.addWidget(self.filterLabel, thisRow + 3, 2, 1, 1)
        self.layout.addWidget(self.filterOrder, thisRow + 3, 3, 1, 1)

        self.zPlanes = QtGui.QComboBox()
        self.zPlanesLabel = QtGui.QLabel('# planes')
        for s in ['All', '1', '2', '3', '4', '5']:
            self.zPlanes.addItem("%s" % s)
        self.layout.addWidget(self.zPlanesLabel, thisRow + 3, 0, 1, 1)
        self.layout.addWidget(self.zPlanes, thisRow + 3, 1, 1, 1)

        ## controls that only appear if there is a time axis
        self.timeControls = [
            self.timeSlider, self.edgeBtn, self.maxBtn, self.meanBtn,
            self.maxBtn2, self.maxMedianBtn, self.filterOrder, self.zPlanes
        ]

        if self.data is not None:
            self.updateImage(self.data)

        self.graphicsItem().sigImageChanged.connect(self.updateHistogram)
        self.levelRgn.sigRegionChanged.connect(self.levelsChanged)
        self.levelRgn.sigRegionChangeFinished.connect(
            self.levelsChangeFinished)