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
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
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)
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))
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)
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)
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)
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))
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
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.))
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())
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)
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)
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
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()
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)