Source code for iocbio.kinetics.handler.roi

from PyQt5.QtCore import pyqtSignal, QObject
from iocbio.kinetics.constants import database_table_roi, database_table_experiment


[docs]class ROIHandler(QObject): """ class that holds ROIs """ sigRois = pyqtSignal(dict, list) sigActiveRoi = pyqtSignal(str) sigActiveRoiAnalyser = pyqtSignal(object) sigActiveRoiType = pyqtSignal(str) sigUpdate = pyqtSignal() # emitted when some stats has changed by analyzers database_table = database_table_roi @staticmethod def database_schema(db): db.query("CREATE TABLE IF NOT EXISTS " + db.table(ROIHandler.database_table) + "(experiment_id text not null, data_id text PRIMARY KEY, type text not null, " + "x0 double precision, x1 double precision, event_name text, event_value double precision, " + "FOREIGN KEY (experiment_id) REFERENCES " + db.table(database_table_experiment) + "(experiment_id) ON DELETE CASCADE" + ")") def __init__(self, database, data, Analyzer): QObject.__init__(self) self.database = database self.data = data self.experiment_id = data.experiment_id self.rois = {} self.current_roi = None self.Analyzer = Analyzer if self.Analyzer is not None and self.Analyzer: if self.database is not None: c = self.database for row in c.query("SELECT data_id, type, x0, x1, event_name, event_value FROM " + self.database.table(ROIHandler.database_table) + " WHERE experiment_id=:experiment_id", experiment_id=self.experiment_id): rdata = self.data.slice(row.x0,row.x1,data_id=row.data_id, event_name=row.event_name,event_value=row.event_value) analyzer = self.Analyzer[row.type](self.database, rdata) self.rois[row.data_id] = { 'type': row.type, 'data': rdata, 'analyzer': analyzer } analyzer.signals.sigUpdate.connect(self.sigUpdate) if not bool(self.rois): for t in Analyzer: sliced_data = Analyzer[t].auto_slicer(data) for k in sliced_data: self.add(rdata = k, roi_type = t) def trigger_updates(self): srt = self.sorted_roi_list self.sigRois.emit(self.rois, srt) if bool(self.rois and len(srt) > 0): self.set_active(srt[0]) self.sigUpdate.emit() def add(self, roi_type, rng=None, rdata=None): if rng is None and rdata is None: return if rng is not None: x0, x1 = rng rdata = self.Analyzer[roi_type].slice(self.data, x0, x1) else: x0, x1 = rdata.xlim() # record in the database first if self.database is not None: c = self.database c.query("INSERT INTO " + self.database.table(ROIHandler.database_table) + "(experiment_id, data_id, type, x0, x1, event_name, event_value) " + "VALUES (:experiment_id, :data_id, :type, :x0, :x1, :event_name, :event_value)", experiment_id=self.experiment_id, data_id=rdata.data_id, type=roi_type, x0=x0, x1=x1, event_name=rdata.event_name, event_value=rdata.event_value) analyzer = self.Analyzer[roi_type](self.database, rdata) self.rois[rdata.data_id] = { 'type': roi_type, 'data': rdata, 'analyzer': analyzer } analyzer.signals.sigUpdate.connect(self.sigUpdate) self.sigRois.emit(self.rois, self.sorted_roi_list) self.set_active(rdata.data_id) def remove(self, data_id): if data_id not in self.rois: return self.rois[data_id]['analyzer'].remove() del self.rois[data_id] if self.database is not None: c = self.database c.query("DELETE FROM " + self.database.table(ROIHandler.database_table) + " WHERE experiment_id=:experiment_id AND data_id=:data_id", experiment_id=self.experiment_id, data_id=data_id) self.sigRois.emit(self.rois, self.sorted_roi_list) self.set_active(None) def update_range(self, roi_id, coords): if roi_id not in self.rois: return roi = self.rois[roi_id] x0, x1 = coords data = self.data.slice(x0, x1, data_id=roi['data'].data_id, event_name=roi['data'].event_name, event_value=roi['data'].event_value) self.rois[roi_id]['data'] = data self.rois[roi_id]['analyzer'].update_data(data) c = self.database c.query("UPDATE " + self.database.table(ROIHandler.database_table) + " SET x0=:x0, x1=:x1 WHERE experiment_id=:experiment_id AND data_id=:data_id", x0=x0, x1=x1, experiment_id=self.experiment_id, data_id=data.data_id) def update_event(self, roi_id, event_name): if roi_id not in self.rois: return self.rois[roi_id]['analyzer'].update_event(event_name) self.rois[roi_id]['data'] = self.rois[roi_id]['analyzer'].data c = self.database data = self.rois[roi_id]['analyzer'].data c.query("UPDATE " + self.database.table(ROIHandler.database_table) + " SET event_name=:event_name, event_value=:event_value WHERE experiment_id=:experiment_id AND data_id=:data_id", event_name=data.event_name, event_value=data.event_value, experiment_id=self.experiment_id, data_id=data.data_id) self.sigUpdate.emit() def set_active(self, roi_id): if self.current_roi == roi_id or (roi_id not in self.rois and roi_id is not None): return self.current_roi = roi_id self.sigActiveRoi.emit(roi_id) if roi_id is not None: self.sigActiveRoiAnalyser.emit(self.rois[self.current_roi]['analyzer']) self.sigActiveRoiType.emit(self.rois[self.current_roi]['type']) else: self.sigActiveRoiAnalyser.emit(None) self.sigActiveRoiType.emit(None) def get_roi_data(self, roi_id): return self.rois[roi_id]['data'] @property def sorted_roi_list(self): if self.database is None: return [] else: c = self.database l = c.query("SELECT data_id FROM " + self.database.table(ROIHandler.database_table) + " WHERE experiment_id=:experiment_id ORDER BY type,x0,x1 ASC", experiment_id=self.experiment_id ) return [el.data_id for el in l]