def loadMap(self, rec): self.getElement('Canvas').clear() self.currentMap = Map(self, rec) self.currentMap.loadStubs() self.currentMap.sPlotItem.sigClicked.connect(self.mapPointClicked) self.getElement('Canvas').addGraphicsItem(self.currentMap.sPlotItem, movable=False) self.invalidate() self.loadFromDB() self.update()
class MapAnalyzer(AnalysisModule): dbIdentity = 'MapAnalyzer' def __init__(self, host): AnalysisModule.__init__(self, host) if self.dataModel is None: raise Exception("MapAnalyzer module requires a data model, but none is loaded yet.") self.currentMap = None self.analysisValid = False self.colorsValid = False self.ctrlLayout = pg.LayoutWidget() self.ctrl = ptree.ParameterTree(showHeader=False) self.ctrlLayout.addWidget(self.ctrl, row=0, col=0) self.recalcBtn = QtGui.QPushButton('Recalculate') self.ctrlLayout.addWidget(self.recalcBtn, row=1, col=0) self.storeBtn = pg.FeedbackButton('Store to DB') self.ctrlLayout.addWidget(self.storeBtn, row=2, col=0) self.loader = Loader(host=self, dm=host.dataManager()) modPath = os.path.abspath(os.path.dirname(__file__)) self.colorMapper = ColorMapper(filePath=os.path.join(modPath, "colorMaps")) self._elements_ = OrderedDict([ ('File Loader', {'type': 'fileInput', 'size': (300, 300), 'host': self, 'showFileTree': False}), ('Map Loader', {'type': 'ctrl', 'object': self.loader, 'size': (300, 300), 'pos': ('below', 'File Loader')}), ('Color Mapper', {'type':'ctrl', 'object': self.colorMapper, 'size': (800,200), 'pos': ('right', 'Map Loader')}), ('Canvas', {'type': 'canvas', 'size': (800, 400), 'pos':('right', 'Color Mapper'), 'args': {'name': 'MapAnalyzer'}}), ('Options', {'type': 'ctrl', 'object': self.ctrlLayout, 'size': (300, 500), 'pos': ('bottom', 'Map Loader')}), ('Data Plot', {'type': 'plot', 'pos': ('top', 'Color Mapper'), 'size': (800, 300)}), ('Score Histogram', {'type': 'plot', 'pos': ('bottom', 'Data Plot'), 'size': (800, 300)}), ('Timeline', {'type': 'plot', 'pos': ('bottom', 'Data Plot'), 'size': (800, 300)}), ('Stats Table', {'type': 'dataTree', 'pos': ('bottom', 'Canvas'), 'size': (800,300)}), ]) host.resize(1100, 800) self.initializeElements() self.filterStage = EventFilter() self.spontRateStage = SpontRateAnalyzer(plot=self.getElement('Timeline', create=True)) self.statsStage = EventStatisticsAnalyzer(histogramPlot=self.getElement('Score Histogram', create=True)) self.regions = RegionMarker(self.getElement('Canvas', create=True)) self.stages = [self.filterStage, self.spontRateStage, self.statsStage, self.regions] params = [ dict(name='Time Ranges', type='group', children=[ dict(name='Direct Start', type='float', value=0.498, suffix='s', step=0.001, siPrefix=True), dict(name='Stimulus', type='float', value=0.5, suffix='s', step=0.001, siPrefix=True), dict(name='Post Start', type='float', value=0.502, suffix='s', step=0.001, siPrefix=True), dict(name='Post Stop', type='float', value=0.700, suffix='s', step=0.001, siPrefix=True), ]), ] ## each processing stage comes with its own set of parameters for stage in self.stages: params.append(stage.parameters()) self.params = ptree.Parameter.create(name='options', type='group', children=params) self.ctrl.setParameters(self.params, showTop=False) canvas = self.getElement('Canvas', create=True) #self.scalebar = pg.ScaleBar(100e-6) #canvas.addGraphicsItem(self.scalebar, name="ScaleBar") self.scalebar = pg.ScaleBar(size=500e-6) self.scalebar.setParentItem(canvas.view) self.scalebar.anchor((1, 1), (1, 1), offset=(-20, -20)) ## Note: need to reconnect this!! #self.params.sigTreeStateChanged.connect(self.invalidate) self.recalcBtn.clicked.connect(self.recalcClicked) self.storeBtn.clicked.connect(self.storeToDB) self.params.param('Time Ranges').sigTreeStateChanged.connect(self.updateTimes) self.getElement('Color Mapper', create=True).sigChanged.connect(self.colorMapChanged) self.regions.sigRegionChanged.connect(self.processRegions) def elementChanged(self, element, old, new): name = element.name() def loadMap(self, rec): self.getElement('Canvas').clear() self.currentMap = Map(self, rec) self.currentMap.loadStubs() self.currentMap.sPlotItem.sigClicked.connect(self.mapPointClicked) self.getElement('Canvas').addGraphicsItem(self.currentMap.sPlotItem, movable=False) self.invalidate() self.loadFromDB() self.update() def loadScan(self, dh): ## called by Map objects to load scans scans = Scan.loadScanSequence(dh, self) #if len(scans) > 1: #raise Exception("Scan sequences not supported yet.") for scan in scans: ci = scan.canvasItem() self.getElement('Canvas').addItem(ci) ci.hide() scan.canvasItem().graphicsItem().sigClicked.connect(self.scanPointClicked) return scans def loadScanFromDB(self, sourceDir): ## Called by Scan as it is loading statTable = self.loader.dbGui.getTableName('Photostim.sites') eventTable = self.loader.dbGui.getTableName('Photostim.events') db = self.loader.dbGui.getDb() stats = db.select(statTable, '*', where={'ProtocolSequenceDir': sourceDir}) events = db.select(eventTable, '*', where={'ProtocolSequenceDir': sourceDir}, toArray=True) return events, stats def loadSpotFromDB(self, sourceDir): ## Called by Scan as it is loading single points statTable = self.loader.dbGui.getTableName('Photostim.sites') eventTable = self.loader.dbGui.getTableName('Photostim.events') db = self.loader.dbGui.getDb() stats = db.select(statTable, '*', where={'ProtocolDir': sourceDir}) events = db.select(eventTable, '*', where={'ProtocolDir': sourceDir}, toArray=True) return events, stats def loadFileRequested(self, fhList): canvas = self.getElement('Canvas') model = self.dataModel with pg.ProgressDialog("Loading data..", 0, len(fhList)) as dlg: for fh in fhList: try: ## TODO: use more clever detection of Scan data here. if fh.isFile() or model.dirType(fh) == 'Cell': canvas.addFile(fh, movable=False) #else: #self.loadScan(fh) return True else: return False except: debug.printExc("Error loading file %s" % fh.name()) return False dlg += 1 if dlg.wasCancelled(): return def getDb(self): db = self.loader.dbGui.getDb() return db def getColor(self, stats, data): ## return the color to represent this data ## merge data together d2 = data.copy() del d2['sites'] d2 = OrderedDict(d2) d2.update(stats) del d2['ProtocolDir'] mapper = self.getElement('Color Mapper') mapper.setArgList(d2.keys()) return mapper.getColor(d2) def colorMapChanged(self): self.colorsValid = False self.update() def update(self): if not self.analysisValid: print "Updating analysis.." map = self.currentMap if map is None: return scans = map.scans ## Get a list of all stimulations in the map and their times. sites = [] for s in scans: sites.extend(s.getTimes()) sites.sort(key=lambda i: i[1]) ## get list of all events events = [] for scan in scans: ev = scan.getAllEvents() if ev is not None: events.append(ev.copy()) ## set up table of per-stimulation data spontRates = np.zeros(len(sites), dtype=[('ProtocolDir', object), ('start', float), ('stop', float), ('spontRate', float), ('filteredSpontRate', float)]) spontRates[:] = [s+(0,0) for s in sites] ## fill with data filtered = None if len(events) > 0: events = np.concatenate(events) filtered = self.filterStage.process(events) ## compute spontaneous rates sr = self.spontRateStage.process(spontRates, filtered) spontRates['spontRate'] = sr['spontRate'] spontRates['filteredSpontRate'] = sr['filteredSpontRate'] else: sr = {'ampMean': 0, 'ampStdev': 0} output = self.statsStage.process(map, spontRates, filtered, sr['ampMean'], sr['ampStdev']) self.analysisValid = True if not self.colorsValid: self.currentMap.recolor() self.colorsValid = True def invalidate(self): print "invalidate." self.analysisValid = False self.colorsValid = False def recalcClicked(self): self.invalidate() self.update() def updateTimes(self): self.params['Spontaneous Rate', 'Stop Time'] = self.params['Time Ranges', 'Direct Start'] self.params['Analysis Methods', 'Stimulus Time'] = self.params['Time Ranges', 'Stimulus'] self.params['Analysis Methods', 'Pre Stop'] = self.params['Time Ranges', 'Direct Start'] self.params['Analysis Methods', 'Post Start'] = self.params['Time Ranges', 'Post Start'] self.params['Analysis Methods', 'Post Stop'] = self.params['Time Ranges', 'Post Stop'] def scanPointClicked(self, gitem, points): plot = self.getElement('Data Plot', create=True) plot.clear() scan = gitem.scan scan.displayData(points[0].data(), plot, 'w') def mapPointClicked(self, gitem, points): plot = self.getElement('Data Plot', create=True) plot.clear() data = [] for p in points: for source in p.data()['sites']: data.append(source) #data.extend(p.data) for i in range(len(data)): scan, fh = data[i] scan.displayData(fh, plot, pen=(i, len(data)*1.3), eventFilter=self.filterStage.process) self.getElement('Stats Table').setData(points[0].data()) def storeToDB(self): try: self.update() ## Determine currently selected table to store to dbui = self.getElement('Map Loader').dbGui identity = self.dbIdentity+'.sites' mapTable = dbui.getTableName('Photostim.maps') table = dbui.getTableName(identity) db = dbui.getDb() if db is None: raise Exception("No DB selected") fields = OrderedDict([ ('Map', {'Type': 'int', 'Link': mapTable}), #('CellDir', 'directory:Cell'), ('FirstSite', 'directory:Protocol'), ('Sites', 'blob'), ('PoissonScore', 'real'), ('PoissonScore_Pre', 'real'), ('PoissonAmpScore', 'real'), ('PoissonAmpScore_Pre', 'real'), ('HasInput', 'int'), ('FirstLatency', 'real'), ('ZScore', 'real'), ('FitAmpSum', 'real'), ('FitAmpSum_Pre', 'real'), ('NumEvents', 'real'), ('SpontRate', 'real'), ('DirectPeak', 'real'), ('Region', 'text'), ]) mapRec = self.currentMap.getRecord() data = [] for spot in self.currentMap.spots: rec = {} for k in fields: if k in spot['data']: rec[k] = spot['data'][k] #rec['CellDir'] = mapRec['cell'] rec['Map'] = self.currentMap.rowID sites = [s[1] for s in spot['data']['sites']] rec['FirstSite'] = sites[0] rec['Sites'] = [db.getDirRowID(s) for s in sites] data.append(rec) with db.transaction(): ## Make sure target table exists and has correct columns, links to input file db.checkTable(table, owner=identity, columns=fields, create=True, addUnknownColumns=True, indexes=[['Map']]) # delete old db.delete(table, where={'Map': self.currentMap.rowID}) # write new with pg.ProgressDialog("Storing map data...", 0, 100) as dlg: for n, nmax in db.iterInsert(table, data, chunkSize=100): dlg.setMaximum(nmax) dlg.setValue(n) if dlg.wasCanceled(): raise HelpfulException("Scan store canceled by user.", msgType='status') self.storeBtn.success() except: self.storeBtn.failure() raise def processRegions(self): ## Compute regions for each spot for spot in self.currentMap.spots: dh = spot['data']['sites'][0][1] pos = spot['pos'] rgn = self.regions.getRegion(pos) spot['data']['Region'] = rgn #print dh,rgn ## Store ROI positions with cell cell = self.currentMap.getRecord()['cell'] rgns = self.regions.getRegions() cell.setInfo(MapAnalyzer_Regions=rgns) def loadFromDB(self): ## read in analysis from DB dbui = self.getElement('Map Loader').dbGui identity = self.dbIdentity+'.sites' mapTable = dbui.getTableName('Photostim.maps') table = dbui.getTableName(identity) db = dbui.getDb() if db is None: raise Exception("No DB selected") if not db.hasTable(table): return None fields = OrderedDict([ ('Map', {'Type': 'int', 'Link': mapTable}), #('Sites', 'blob'), ('PoissonScore', 'real'), ('PoissonScore_Pre', 'real'), ('PoissonAmpScore', 'real'), ('PoissonAmpScore_Pre', 'real'), ('HasInput', 'int'), ('FirstLatency', 'real'), ('ZScore', 'real'), ('FitAmpSum', 'real'), ('FitAmpSum_Pre', 'real'), ('NumEvents', 'real'), ('SpontRate', 'real'), ('DirectPeak', 'real'), ('Region', 'text'), ]) #mapRec = self.currentMap.getRecord() recs = db.select(table, ['rowid', '*'], where={'Map': self.currentMap.rowID}) if len(recs) == len(self.currentMap.spots): for i, spot in enumerate(self.currentMap.spots): for k in fields.keys() + recs[i].keys(): spot['data'][k] = recs[i].get(k, None) self.analysisValid = True print "reloaded analysis from DB", self.currentMap.rowID else: print "analysis incomplete:", len(recs), len(self.currentMap.spots)
class MapAnalyzer(AnalysisModule): dbIdentity = 'MapAnalyzer' def __init__(self, host): AnalysisModule.__init__(self, host) if self.dataModel is None: raise Exception( "MapAnalyzer module requires a data model, but none is loaded yet." ) self.currentMap = None self.analysisValid = False self.colorsValid = False self.ctrlLayout = pg.LayoutWidget() self.ctrl = ptree.ParameterTree(showHeader=False) self.ctrlLayout.addWidget(self.ctrl, row=0, col=0) self.recalcBtn = QtGui.QPushButton('Recalculate') self.ctrlLayout.addWidget(self.recalcBtn, row=1, col=0) self.storeBtn = pg.FeedbackButton('Store to DB') self.ctrlLayout.addWidget(self.storeBtn, row=2, col=0) self.loader = Loader(host=self, dm=host.dataManager()) modPath = os.path.abspath(os.path.dirname(__file__)) self.colorMapper = ColorMapper( filePath=os.path.join(modPath, "colorMaps")) self._elements_ = OrderedDict([ ('File Loader', { 'type': 'fileInput', 'size': (300, 300), 'host': self, 'showFileTree': False }), ('Map Loader', { 'type': 'ctrl', 'object': self.loader, 'size': (300, 300), 'pos': ('below', 'File Loader') }), ('Color Mapper', { 'type': 'ctrl', 'object': self.colorMapper, 'size': (800, 200), 'pos': ('right', 'Map Loader') }), ('Canvas', { 'type': 'canvas', 'size': (800, 400), 'pos': ('right', 'Color Mapper'), 'args': { 'name': 'MapAnalyzer' } }), ('Options', { 'type': 'ctrl', 'object': self.ctrlLayout, 'size': (300, 500), 'pos': ('bottom', 'Map Loader') }), ('Data Plot', { 'type': 'plot', 'pos': ('top', 'Color Mapper'), 'size': (800, 300) }), ('Score Histogram', { 'type': 'plot', 'pos': ('bottom', 'Data Plot'), 'size': (800, 300) }), ('Timeline', { 'type': 'plot', 'pos': ('bottom', 'Data Plot'), 'size': (800, 300) }), ('Stats Table', { 'type': 'dataTree', 'pos': ('bottom', 'Canvas'), 'size': (800, 300) }), ]) host.resize(1100, 800) self.initializeElements() self.filterStage = EventFilter() self.spontRateStage = SpontRateAnalyzer( plot=self.getElement('Timeline', create=True)) self.statsStage = EventStatisticsAnalyzer( histogramPlot=self.getElement('Score Histogram', create=True)) self.regions = RegionMarker(self.getElement('Canvas', create=True)) self.stages = [ self.filterStage, self.spontRateStage, self.statsStage, self.regions ] params = [ dict(name='Time Ranges', type='group', children=[ dict(name='Direct Start', type='float', value=0.498, suffix='s', step=0.001, siPrefix=True), dict(name='Stimulus', type='float', value=0.5, suffix='s', step=0.001, siPrefix=True), dict(name='Post Start', type='float', value=0.502, suffix='s', step=0.001, siPrefix=True), dict(name='Post Stop', type='float', value=0.700, suffix='s', step=0.001, siPrefix=True), ]), ] ## each processing stage comes with its own set of parameters for stage in self.stages: params.append(stage.parameters()) self.params = ptree.Parameter.create(name='options', type='group', children=params) self.ctrl.setParameters(self.params, showTop=False) canvas = self.getElement('Canvas', create=True) #self.scalebar = pg.ScaleBar(100e-6) #canvas.addGraphicsItem(self.scalebar, name="ScaleBar") self.scalebar = pg.ScaleBar(size=500e-6) self.scalebar.setParentItem(canvas.view) self.scalebar.anchor((1, 1), (1, 1), offset=(-20, -20)) ## Note: need to reconnect this!! #self.params.sigTreeStateChanged.connect(self.invalidate) self.recalcBtn.clicked.connect(self.recalcClicked) self.storeBtn.clicked.connect(self.storeToDB) self.params.param('Time Ranges').sigTreeStateChanged.connect( self.updateTimes) self.getElement('Color Mapper', create=True).sigChanged.connect(self.colorMapChanged) self.regions.sigRegionChanged.connect(self.processRegions) def elementChanged(self, element, old, new): name = element.name() def loadMap(self, rec): self.getElement('Canvas').clear() self.currentMap = Map(self, rec) self.currentMap.loadStubs() self.currentMap.sPlotItem.sigClicked.connect(self.mapPointClicked) self.getElement('Canvas').addGraphicsItem(self.currentMap.sPlotItem, movable=False) self.invalidate() self.loadFromDB() self.update() def loadScan(self, dh): ## called by Map objects to load scans scans = Scan.loadScanSequence(dh, self) #if len(scans) > 1: #raise Exception("Scan sequences not supported yet.") for scan in scans: ci = scan.canvasItem() self.getElement('Canvas').addItem(ci) ci.hide() scan.canvasItem().graphicsItem().sigClicked.connect( self.scanPointClicked) return scans def loadScanFromDB(self, sourceDir): ## Called by Scan as it is loading statTable = self.loader.dbGui.getTableName('Photostim.sites') eventTable = self.loader.dbGui.getTableName('Photostim.events') db = self.loader.dbGui.getDb() stats = db.select(statTable, '*', where={'ProtocolSequenceDir': sourceDir}) events = db.select(eventTable, '*', where={'ProtocolSequenceDir': sourceDir}, toArray=True) return events, stats def loadSpotFromDB(self, sourceDir): ## Called by Scan as it is loading single points statTable = self.loader.dbGui.getTableName('Photostim.sites') eventTable = self.loader.dbGui.getTableName('Photostim.events') db = self.loader.dbGui.getDb() stats = db.select(statTable, '*', where={'ProtocolDir': sourceDir}) events = db.select(eventTable, '*', where={'ProtocolDir': sourceDir}, toArray=True) return events, stats def loadFileRequested(self, fhList): canvas = self.getElement('Canvas') model = self.dataModel with pg.ProgressDialog("Loading data..", 0, len(fhList)) as dlg: for fh in fhList: try: ## TODO: use more clever detection of Scan data here. if fh.isFile() or model.dirType(fh) == 'Cell': canvas.addFile(fh, movable=False) #else: #self.loadScan(fh) return True else: return False except: debug.printExc("Error loading file %s" % fh.name()) return False dlg += 1 if dlg.wasCanceled(): return def getDb(self): db = self.loader.dbGui.getDb() return db def getColor(self, stats, data): ## return the color to represent this data ## merge data together d2 = data.copy() del d2['sites'] d2 = OrderedDict(d2) d2.update(stats) del d2['ProtocolDir'] mapper = self.getElement('Color Mapper') mapper.setArgList(d2.keys()) return mapper.getColor(d2) def colorMapChanged(self): self.colorsValid = False self.update() def update(self): if not self.analysisValid: print "Updating analysis.." map = self.currentMap if map is None: return scans = map.scans ## Get a list of all stimulations in the map and their times. sites = [] for s in scans: sites.extend(s.getTimes()) sites.sort(key=lambda i: i[1]) ## get list of all events events = [] for scan in scans: ev = scan.getAllEvents() if ev is not None: events.append(ev.copy()) ## set up table of per-stimulation data spontRates = np.zeros(len(sites), dtype=[('ProtocolDir', object), ('start', float), ('stop', float), ('spontRate', float), ('filteredSpontRate', float)]) spontRates[:] = [s + (0, 0) for s in sites] ## fill with data filtered = None if len(events) > 0: events = np.concatenate(events) filtered = self.filterStage.process(events) ## compute spontaneous rates sr = self.spontRateStage.process(spontRates, filtered) spontRates['spontRate'] = sr['spontRate'] spontRates['filteredSpontRate'] = sr['filteredSpontRate'] else: sr = {'ampMean': 0, 'ampStdev': 0} output = self.statsStage.process(map, spontRates, filtered, sr['ampMean'], sr['ampStdev']) self.analysisValid = True if not self.colorsValid: self.currentMap.recolor() self.colorsValid = True def invalidate(self): print "invalidate." self.analysisValid = False self.colorsValid = False def recalcClicked(self): self.invalidate() self.update() def updateTimes(self): self.params['Spontaneous Rate', 'Stop Time'] = self.params['Time Ranges', 'Direct Start'] self.params['Analysis Methods', 'Stimulus Time'] = self.params['Time Ranges', 'Stimulus'] self.params['Analysis Methods', 'Pre Stop'] = self.params['Time Ranges', 'Direct Start'] self.params['Analysis Methods', 'Post Start'] = self.params['Time Ranges', 'Post Start'] self.params['Analysis Methods', 'Post Stop'] = self.params['Time Ranges', 'Post Stop'] def scanPointClicked(self, gitem, points): plot = self.getElement('Data Plot', create=True) plot.clear() scan = gitem.scan scan.displayData(points[0].data(), plot, 'w') def mapPointClicked(self, gitem, points): plot = self.getElement('Data Plot', create=True) plot.clear() data = [] for p in points: for source in p.data()['sites']: data.append(source) #data.extend(p.data) for i in range(len(data)): scan, fh = data[i] scan.displayData(fh, plot, pen=(i, len(data) * 1.3), eventFilter=self.filterStage.process) self.getElement('Stats Table').setData(points[0].data()) def storeToDB(self): try: self.update() ## Determine currently selected table to store to dbui = self.getElement('Map Loader').dbGui identity = self.dbIdentity + '.sites' mapTable = dbui.getTableName('Photostim.maps') table = dbui.getTableName(identity) db = dbui.getDb() if db is None: raise Exception("No DB selected") fields = OrderedDict([ ('Map', { 'Type': 'int', 'Link': mapTable }), #('CellDir', 'directory:Cell'), ('FirstSite', 'directory:Protocol'), ('Sites', 'blob'), ('PoissonScore', 'real'), ('PoissonScore_Pre', 'real'), ('PoissonAmpScore', 'real'), ('PoissonAmpScore_Pre', 'real'), ('HasInput', 'int'), ('FirstLatency', 'real'), ('ZScore', 'real'), ('FitAmpSum', 'real'), ('FitAmpSum_Pre', 'real'), ('NumEvents', 'real'), ('SpontRate', 'real'), ('DirectPeak', 'real'), ('Region', 'text'), ]) mapRec = self.currentMap.getRecord() data = [] for spot in self.currentMap.spots: rec = {} for k in fields: if k in spot['data']: rec[k] = spot['data'][k] #rec['CellDir'] = mapRec['cell'] rec['Map'] = self.currentMap.rowID sites = [s[1] for s in spot['data']['sites']] rec['FirstSite'] = sites[0] rec['Sites'] = [db.getDirRowID(s) for s in sites] data.append(rec) with db.transaction(): ## Make sure target table exists and has correct columns, links to input file db.checkTable(table, owner=identity, columns=fields, create=True, addUnknownColumns=True, indexes=[['Map']]) # delete old db.delete(table, where={'Map': self.currentMap.rowID}) # write new with pg.ProgressDialog("Storing map data...", 0, 100) as dlg: for n, nmax in db.iterInsert(table, data, chunkSize=100): dlg.setMaximum(nmax) dlg.setValue(n) if dlg.wasCanceled(): raise HelpfulException( "Scan store canceled by user.", msgType='status') self.storeBtn.success() except: self.storeBtn.failure() raise def processRegions(self): ## Compute regions for each spot for spot in self.currentMap.spots: dh = spot['data']['sites'][0][1] pos = spot['pos'] rgn = self.regions.getRegion(pos) spot['data']['Region'] = rgn #print dh,rgn ## Store ROI positions with cell cell = self.currentMap.getRecord()['cell'] rgns = self.regions.getRegions() cell.setInfo(MapAnalyzer_Regions=rgns) def loadFromDB(self): ## read in analysis from DB dbui = self.getElement('Map Loader').dbGui identity = self.dbIdentity + '.sites' mapTable = dbui.getTableName('Photostim.maps') table = dbui.getTableName(identity) db = dbui.getDb() if db is None: raise Exception("No DB selected") if not db.hasTable(table): return None fields = OrderedDict([ ('Map', { 'Type': 'int', 'Link': mapTable }), #('Sites', 'blob'), ('PoissonScore', 'real'), ('PoissonScore_Pre', 'real'), ('PoissonAmpScore', 'real'), ('PoissonAmpScore_Pre', 'real'), ('HasInput', 'int'), ('FirstLatency', 'real'), ('ZScore', 'real'), ('FitAmpSum', 'real'), ('FitAmpSum_Pre', 'real'), ('NumEvents', 'real'), ('SpontRate', 'real'), ('DirectPeak', 'real'), ('Region', 'text'), ]) #mapRec = self.currentMap.getRecord() recs = db.select(table, ['rowid', '*'], where={'Map': self.currentMap.rowID}) if len(recs) == len(self.currentMap.spots): for i, spot in enumerate(self.currentMap.spots): for k in fields.keys() + recs[i].keys(): spot['data'][k] = recs[i].get(k, None) self.analysisValid = True print "reloaded analysis from DB", self.currentMap.rowID else: print "analysis incomplete:", len(recs), len(self.currentMap.spots)