class ActigraphDBTest2(unittest.TestCase): @timing def setUp(self): np.set_printoptions(suppress=True) print(__file__ + ' Creating database') # Will read already existing file self.db = DBManager('actigraph.db', False, False) @timing def tearDown(self): self.db.commit() def test_read_all_participant(self): participants = self.db.get_all_participants() print(participants) for participant in participants: print(participant, participant.group) def test_read_all_data(self): recordsets = self.db.get_all_recordsets() for record in recordsets: all_data = self.db.get_all_sensor_data(record, convert=True) for data in all_data: for time in data.to_time_series()['time']: print('time', time) break
def test_get_all_recordsets(self): manager = DBManager(filename='openimu.db', overwrite=True) # Participant information group = manager.update_group( Group(name='My Group', description='My Group Description')) name = 'Participant Name' description = 'Participant Description' participant1 = manager.update_participant( Participant(name=name, description=description, group=group)) participant2 = manager.update_participant( Participant(name=name, description=description, group=group)) participant3 = manager.update_participant( Participant(name=name, description=description, group=group)) count = 10 recordsets1 = [] recordsets2 = [] # Adding recordsets for i in range(0, count): time1 = datetime.datetime.now() time2 = datetime.datetime.now() recordsets1.append( manager.add_recordset(participant1, 'Record Name' + str(i), time1, time2)) recordsets2.append( manager.add_recordset(participant2, 'Record Name' + str(i), time1, time2)) # Compare size all_from_participant_1 = manager.get_all_recordsets(participant1) all_from_participant_2 = manager.get_all_recordsets(participant2) self.assertEqual(len(all_from_participant_1), len(recordsets1)) self.assertEqual(len(all_from_participant_2), len(recordsets2)) self.assertEqual(len(manager.get_all_recordsets()), len(recordsets1) + len(recordsets2)) self.assertEqual(0, len(manager.get_all_recordsets(participant3))) # Compare contents for i in range(0, count): self.assertEqual(recordsets1[i], all_from_participant_1[i]) self.assertEqual(recordsets2[i], all_from_participant_2[i]) manager.close()
def test_loading(self): manager = DBManager('test.db', overwrite=True) participant = Participant(name='My Participant', description='Participant Description') manager.update_participant(participant) # Import to database importer = ActigraphImporter(manager, participant) results = importer.load('../../../resources/samples/test.gt3x') samples = 0 for activity in results[1]['activity']: samples += 3 * len(activity[1]) print('samples imported (each channels)', samples) importer.import_to_database(results) # Reload from database manager = DBManager('test.db') recordsets = manager.get_all_recordsets() self.assertGreater(len(recordsets), 0) loaded_samples = 0 for record in recordsets: # Get all sensors in record sensors = manager.get_all_sensors() for sensor in sensors: if sensor.id_sensor_type == SensorType.ACCELEROMETER: channels = manager.get_all_channels(sensor=sensor) for channel in channels: print('processing channel: ', channel) self.assertEqual(channel.id_sensor, sensor.id_sensor, "id_sensor test for channel") # Will get all data (converted to floats) channel_data = manager.get_all_sensor_data( recordset=record, convert=True, channel=channel) print('channel_data_length', len(channel_data)) for sensor_data in channel_data: self.assertEqual(sensor_data.id_channel, channel.id_channel, "id_channel test for data") self.assertEqual(sensor_data.id_sensor, sensor.id_sensor, "id_sensor test data") loaded_samples += len(sensor_data.data) self.assertEqual(samples, loaded_samples)
def test_loading(self): manager = DBManager('test.db', overwrite=True) participant = Participant(name='My Participant', description='Participant Description') manager.update_participant(participant) # Import to database importer = WIMUImporter(manager, participant) # results = importer.load('../../../resources/samples/WIMU_ACC_GPS_GYRO_PreProcess.zip') results = importer.load( '../../../resources/samples/REPAR_Sujet7_Semaine_T4.zip') importer.import_to_database(results) recordsets = manager.get_all_recordsets(participant) print('recordsets', recordsets) self.assertGreater(len(recordsets), 0)
def test_async_loading(self): manager = DBManager('test.db', overwrite=True) participant = Participant(name='My Participant', description='Participant Description') manager.update_participant(participant) importer = ActigraphImporter(manager, participant) print('Starting threads...') # Start threads threads = [] for i in range(0, 1): threads.append( importer.async_load('../../../resources/samples/test.gt3x')) print('Waiting for threads...') # Wait for threads for t in threads: t.join() recordsets = manager.get_all_recordsets(participant) print('recordsets', recordsets) self.assertGreater(len(recordsets), 0)
# Create importer importer = ActigraphImporter(db_manager, participant) # Load content of the file to the database data_results = importer.load('../../resources/samples/test.gt3x') importer.import_to_database(data_results) if not os.path.isfile(db_filename): print('importing actigraph data') import_data() manager = DBManager(db_filename) # Get recordsets recordsets = manager.get_all_recordsets() for record in recordsets: # Get all sensors in record sensors = manager.get_all_sensors() for sensor in sensors: if sensor.id_sensor_type == SensorType.ACCELEROMETER: print('Found Accelerometer') channels = manager.get_all_channels(sensor=sensor) for channel in channels: if channel.label == 'Accelerometer_Y': print('Processing Channel :', channel) # Will get all data (converted to floats) channel_data = manager.get_all_sensor_data( recordset=record,
class MainWindow(QMainWindow): currentFileName = '' dbMan = [] currentDataSet = DataSet() currentRecordsets = [] def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.UI = Ui_MainWindow() self.UI.setupUi(self) self.UI.dockToolBar.setTitleBarWidget(QWidget()) self.UI.dockLog.hide() self.add_to_log("OpenIMU - Prêt à travailler.", LogTypes.LOGTYPE_INFO) # Setup signals and slots self.setup_signals() self.show_start_window() def __del__(self): # Restore sys.stdout sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ def show_start_window(self): self.clear_main_widgets() self.showMinimized() start_window = StartWindow(self) if start_window.exec() == QDialog.Rejected: # User closed the dialog - exits! sys.exit(0) # Init database manager self.currentFileName = start_window.fileName self.dbMan = DBManager(self.currentFileName) # Maximize window self.showMaximized() # Load data self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO) self.currentDataSet = self.dbMan.get_dataset() self.load_data_from_dataset() self.UI.treeDataSet.setCurrentItem(None) self.UI.treeDataSet.owner = self # self.loadDemoData() self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE) # If we need to import data, show the import dialog if start_window.importing: self.import_requested() gc.collect() def setup_signals(self): self.UI.treeDataSet.itemClicked.connect(self.tree_item_clicked) self.UI.btnDataSetInfos.clicked.connect(self.infos_requested) self.UI.btnAddGroup.clicked.connect(self.new_group_requested) self.UI.btnAddParticipant.clicked.connect( self.new_participant_requested) self.UI.treeDataSet.participantDragged.connect( self.participant_was_dragged) self.UI.btnDelete.clicked.connect(self.delete_requested) self.UI.btnImport.clicked.connect(self.import_requested) self.UI.btnExportCSV.clicked.connect(self.export_csv_requested) self.UI.dockDataset.visibilityChanged.connect( self.UI.btnShowDataset.setChecked) # self.UI.dockLog.visibilityChanged.connect(self.toggle_log) self.UI.btnShowDataset.clicked.connect(self.toggle_dataset) self.UI.btnShowLog.clicked.connect(self.toggle_log) self.UI.btnTransfer.clicked.connect(self.transfer_requested) self.UI.btnClose.clicked.connect(self.db_close_requested) self.UI.btnCompact.clicked.connect(self.db_compact_requested) self.UI.btnProcess.clicked.connect(self.process_data_requested) def console_log_normal(self, text): self.add_to_log(text, LogTypes.LOGTYPE_DEBUG) def console_log_error(self, text): self.add_to_log(text, LogTypes.LOGTYPE_ERROR) @pyqtSlot() def load_data_from_dataset(self): self.UI.treeDataSet.clear() self.clear_main_widgets() # Groups groups = self.dbMan.get_all_groups() for group in groups: self.UI.treeDataSet.update_group(group) # Participants participants = self.dbMan.get_all_participants() for participant in participants: self.UI.treeDataSet.update_participant(participant) # Recordsets recordsets = self.dbMan.get_all_recordsets() for recordset in recordsets: self.UI.treeDataSet.update_recordset(recordset) # Results results = self.dbMan.get_all_processed_data() for result in results: self.UI.treeDataSet.update_result(result) def update_group(self, group): item = self.UI.treeDataSet.update_group(group) self.UI.treeDataSet.setCurrentItem(item) def update_participant(self, participant): item = self.UI.treeDataSet.update_participant(participant) self.UI.treeDataSet.setCurrentItem(item) def clear_main_widgets(self): for i in reversed(range(self.UI.frmMain.layout().count())): self.UI.frmMain.layout().itemAt(i).widget().setParent(None) def show_group(self, group=None): self.clear_main_widgets() group_widget = GroupWindow(dbManager=self.dbMan, group=group) self.UI.frmMain.layout().addWidget(group_widget) group_widget.dataSaved.connect(self.data_was_saved) group_widget.dataCancelled.connect(self.data_was_cancelled) def show_participant(self, participant=None, base_group=None): self.clear_main_widgets() part_widget = ParticipantWindow(dbManager=self.dbMan, participant=participant, default_group=base_group) self.UI.frmMain.layout().addWidget(part_widget) part_widget.dataSaved.connect(self.data_was_saved) part_widget.dataCancelled.connect(self.data_was_cancelled) @pyqtSlot('QString', int) def add_to_log(self, text, log_type): if text == ' ' or text == '\n': return log_format = "" if log_type == LogTypes.LOGTYPE_INFO: log_format = "<span style='color:black'>" if log_type == LogTypes.LOGTYPE_WARNING: log_format = "<span style='color:orange;font-style:italic'>" if log_type == LogTypes.LOGTYPE_ERROR: log_format = "<span style='color:red;font-weight:bold'>" if log_type == LogTypes.LOGTYPE_DEBUG: log_format = "<span style='color:grey;font-style:italic'>" if log_type == LogTypes.LOGTYPE_DONE: log_format = "<span style='color:green;font-weight:bold'>" self.UI.txtLog.append("<span style='color:grey'>" + datetime.now().strftime("%H:%M:%S.%f") + " </span>" + log_format + text + "</span>") self.UI.txtLog.ensureCursorVisible() QApplication.processEvents() def get_current_widget_data_type(self): # TODO: checks! return self.UI.frmMain.layout().itemAt(0).widget().data_type ###################### @pyqtSlot(bool) def toggle_dataset(self, visibility): self.UI.dockDataset.setVisible(visibility) @pyqtSlot(bool) def toggle_log(self, visibility): self.UI.dockLog.setVisible(visibility) # self.UI.btnShowLog.setChecked(visibility) if visibility: sys.stdout = StdConsoleLogger(self.console_log_normal) sys.stderr = StdConsoleLogger(self.console_log_error) else: sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ # print("Test!") @pyqtSlot() def import_requested(self): importer = ImportBrowser(data_manager=self.dbMan) importer.participant_added.connect(self.load_data_from_dataset) importer.log_request.connect(self.add_to_log) importer.setStyleSheet(self.styleSheet()) if importer.exec() == QDialog.Accepted: self.load_data_from_dataset() gc.collect() @pyqtSlot() def export_csv_requested(self): exporter = ExportWindow(self.dbMan, self) exporter.setStyleSheet(self.styleSheet()) if exporter.exec() == QDialog.Accepted: print("Accepted") @pyqtSlot() def infos_requested(self): infos_window = ImportWindow(dataset=self.currentDataSet, filename=self.currentFileName) infos_window.setStyleSheet(self.styleSheet()) infos_window.noImportUI = True infos_window.infosOnly = True if infos_window.exec() != QDialog.Rejected: self.currentDataSet.name = infos_window.dataSet.name @pyqtSlot() def process_data_requested(self): if self.currentRecordsets: # Display Process Window proc_window = ProcessSelectWindow( data_manager=self.dbMan, recordsets=self.currentRecordsets, parent=self) if proc_window.exec() == QDialog.Accepted: self.UI.treeDataSet.update_item("result", proc_window.processed_data) self.UI.treeDataSet.select_item( "result", proc_window.processed_data.id_processed_data) @pyqtSlot() def db_close_requested(self): msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}") msg.setText( "Cet ensemble de données sera fermé. Désirez-vous poursuivre?") msg.setWindowTitle("Fermeture?") msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rval = msg.exec() if rval == QMessageBox.Yes: self.dbMan.close() self.add_to_log("Fichier " + self.currentFileName + " fermé.", LogTypes.LOGTYPE_INFO) self.hide() self.show_start_window() @pyqtSlot() def db_compact_requested(self): msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}") msg.setText( "Le fichier de données sera nettoyé. Ceci peut prendre un certain temps. \n" "Désirez-vous poursuivre?") msg.setWindowTitle("Compactage des données") msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rval = msg.exec() if rval == QMessageBox.Yes: task = SimpleTask("Compactage des données", self.dbMan.compact) process = BackgroundProcess([task]) dialog = ProgressDialog(process, 'Nettoyage', self) process.start() dialog.exec() @pyqtSlot() def new_group_requested(self): self.show_group() @pyqtSlot() def new_participant_requested(self): # Check if we can get a root item (group) for the current selected item or not item = self.UI.treeDataSet.currentItem() if item is not None: while item.parent() is not None: item = item.parent() default_group = None if self.UI.treeDataSet.get_item_type(item) == "group": default_group = self.UI.treeDataSet.groups[ self.UI.treeDataSet.get_item_id(item)] self.show_participant(base_group=default_group) @pyqtSlot(Participant) def participant_was_dragged(self, participant): self.dbMan.update_participant(participant) self.update_participant(participant) @pyqtSlot(QTreeWidgetItem, int) def tree_item_clicked(self, item: QTreeWidgetItem, _: int): # print(item.text(column)) item_id = self.UI.treeDataSet.get_item_id(item) item_type = self.UI.treeDataSet.get_item_type(item) # Clear all widgets self.clear_main_widgets() self.UI.btnProcess.setEnabled(False) self.currentRecordsets = [] if item_type == "group": self.show_group(self.UI.treeDataSet.groups[item_id]) # groupWidget = GroupWindow(dbManager=self.dbMan, group = self.UI.treeDataSet.groups[item_id]) # self.UI.frmMain.layout().addWidget(groupWidget) if item_type == "participant": self.show_participant(self.UI.treeDataSet.participants[item_id]) if item_type == "recordsets" or item_type == "recordset" or item_type == "subrecord" or item_type == "date": if item_type == "recordsets": part = self.UI.treeDataSet.participants[ self.UI.treeDataSet.get_item_id(item.parent())] self.currentRecordsets = self.dbMan.get_all_recordsets( participant=part) elif item_type == "date": # Find associated participant id_participant = self.UI.treeDataSet.get_item_id( item.parent().parent()) part = self.UI.treeDataSet.participants[id_participant] search_date = self.UI.treeDataSet.dates[ Treedatawidget.get_date_id(item.text(0), id_participant)] self.currentRecordsets = self.dbMan.get_all_recordsets( participant=part, start_date=search_date) else: self.currentRecordsets = [ self.UI.treeDataSet.recordsets[item_id] ] records_widget = RecordsetWindow(manager=self.dbMan, recordset=self.currentRecordsets, parent=self) # records_widget.setStyleSheet(self.styleSheet() + records_widget.styleSheet()) self.UI.frmMain.layout().addWidget(records_widget) records_widget.dataDisplayRequest.connect( self.UI.treeDataSet.select_item) records_widget.dataUpdateRequest.connect( self.UI.treeDataSet.update_item) self.UI.btnProcess.setEnabled(True) if item_type == "result": result_widget = ResultWindow( manager=self.dbMan, results=self.UI.treeDataSet.results[item_id], parent=self) self.UI.frmMain.layout().addWidget(result_widget) item.setExpanded(True) # self.UI.frmMain.update() @pyqtSlot() def data_was_saved(self): item_type = self.get_current_widget_data_type() if item_type == "group": group = self.UI.frmMain.layout().itemAt(0).widget().group self.update_group(group) self.add_to_log("Groupe " + group.name + " mis à jour.", LogTypes.LOGTYPE_DONE) if item_type == "participant": part = self.UI.frmMain.layout().itemAt(0).widget().participant self.update_participant(part) self.add_to_log("Participant " + part.name + " mis à jour.", LogTypes.LOGTYPE_DONE) @pyqtSlot() def data_was_cancelled(self): item_type = self.get_current_widget_data_type() if item_type == "group": if self.UI.frmMain.layout().itemAt(0).widget().group is None: self.clear_main_widgets() if item_type == "participant": if self.UI.frmMain.layout().itemAt(0).widget().participant is None: self.clear_main_widgets() @pyqtSlot() def delete_requested(self): item_id = self.UI.treeDataSet.get_item_id( self.UI.treeDataSet.currentItem()) item_type = self.UI.treeDataSet.get_item_type( self.UI.treeDataSet.currentItem()) # if item_type == "recordsets" or item_type == "results": # return msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}") msg.setText("Désirez-vous vraiment supprimer \"" + self.UI.treeDataSet.currentItem().text(0) + "\" et tous les éléments associés?") msg.setWindowTitle("Confirmation de suppression") msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rval = msg.exec() if rval == QMessageBox.Yes: item_name = self.UI.treeDataSet.currentItem().text(0) tasks = [] if item_type == "group": group = self.UI.treeDataSet.groups[item_id] self.UI.treeDataSet.remove_group(group) task = SimpleTask("Suppression de '" + group.name + "'", self.dbMan.delete_group, group) tasks.append(task) if item_type == "participant": part = self.UI.treeDataSet.participants[item_id] self.UI.treeDataSet.remove_participant(part) task = SimpleTask("Suppression de '" + part.name + "'", self.dbMan.delete_participant, part) tasks.append(task) if item_type == "recordset": # Find and remove all related results for result in self.UI.treeDataSet.results.values(): if result is not None: for ref in result.processed_data_ref: if ref.recordset.id_recordset == item_id: self.UI.treeDataSet.remove_result(result) task = SimpleTask( "Suppression de '" + result.name + "'", self.dbMan.delete_processed_data, result) tasks.append(task) # self.dbMan.delete_processed_data(result) break recordset = self.UI.treeDataSet.recordsets[item_id] task = SimpleTask("Suppression de '" + recordset.name + "'", self.dbMan.delete_recordset, recordset) tasks.append(task) # self.dbMan.delete_recordset(recordset) self.UI.treeDataSet.remove_recordset(recordset) if item_type == "result": result = self.UI.treeDataSet.results[item_id] task = SimpleTask("Suppression de '" + result.name + "'", self.dbMan.delete_processed_data, result) tasks.append(task) self.UI.treeDataSet.remove_result(result) # self.dbMan.delete_processed_data(result) if item_type == "date": # Delete all recordsets related to that date id_participant = self.UI.treeDataSet.get_item_id( self.UI.treeDataSet.currentItem().parent().parent()) search_date = self.UI.treeDataSet.dates[ Treedatawidget.get_date_id( self.UI.treeDataSet.currentItem().text(0), id_participant)] recordsets = self.dbMan.get_all_recordsets( start_date=search_date) part_id = None for recordset in recordsets: if part_id is None: part_id = recordset.id_participant task = SimpleTask( "Suppression de '" + recordset.name + "'", self.dbMan.delete_recordset, recordset) tasks.append(task) self.UI.treeDataSet.remove_recordset(recordset) self.UI.treeDataSet.remove_date( self.UI.treeDataSet.currentItem().text(0), part_id) if item_type == "recordsets": # Delete all recordsets for that participant participant = self.UI.treeDataSet.participants[ self.UI.treeDataSet.get_item_id( self.UI.treeDataSet.currentItem().parent())] recordsets = self.dbMan.get_all_recordsets( participant=participant) for recordset in recordsets: task = SimpleTask( "Suppression de '" + recordset.name + "'", self.dbMan.delete_recordset, recordset) tasks.append(task) self.UI.treeDataSet.remove_recordset(recordset) # Remove all dates from the view self.UI.treeDataSet.remove_dates_for_participant( participant.id_participant) if item_type == "results": pass if tasks: process = BackgroundProcess(tasks) # Create progress dialog dialog = ProgressDialog(process, 'Suppression', self) # Start tasks process.start() dialog.exec() # self.dbMan.clean_db() self.add_to_log(item_name + " a été supprimé.", LogTypes.LOGTYPE_DONE) self.clear_main_widgets() # def closeEvent(self, event): # return def create_chart_view(self, test_data=False): chart_view = IMUChartView(self) if test_data is True: chart_view.add_test_data() return chart_view @pyqtSlot() def transfer_requested(self): # import_man = ImportManager(dbmanager=self.dbMan, dirs=True, stream=True, parent=self) # # TODO: More intelligent refresh! # import_man.participant_added.connect(self.load_data_from_dataset) # # if import_man.exec() == QDialog.Accepted: stream_diag = StreamWindow(parent=self) stream_diag.exec() # Do the actual import # msg = QMessageBox(self) # msg.setIcon(QMessageBox.Question) # msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}") # # msg.setText("Procéder à l'importation des données?") # msg.setWindowTitle("Importer?") # msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) # # rval = msg.exec() # if rval == QMessageBox.Yes: if stream_diag.folders_to_import: # Match windows matcher = ImportMatchDialog(dbmanager=self.dbMan, datas=stream_diag.folders_to_import, parent=self) if matcher.exec() == QDialog.Accepted: # for file_name, file_dataname in file_list.items(): # part = matcher.data_match[file_dataname] # file_match[file_name] = part # Build import list files = matcher.get_files_match( stream_diag.get_data_save_path()) # Start import process import_browser = ImportBrowser(data_manager=self.dbMan, parent=self) import_browser.log_request.connect(self.add_to_log) importer_id = StreamerTypes.value_importer_types[ stream_diag.get_streamer_type()] importer_name = ImporterTypes.value_names[importer_id] for file_name, file_part in files.items(): import_browser.add_file_to_list(file_name, importer_name, importer_id, file_part) import_browser.ok_clicked() # Delete files after transfer? import shutil if not stream_diag.get_delete_files_after_import(): # Move files to "Imported" folder import os target_dir = stream_diag.get_base_data_save_path( ) + os.sep + "Imported" FileManager.merge_folders(stream_diag.get_data_save_path(), target_dir) # Remove transfered files shutil.rmtree(stream_diag.get_data_save_path()) self.load_data_from_dataset()
class MainWindow(QMainWindow): currentFileName = '' dbMan = [] currentDataSet = DataSet() def __init__(self, parent=None): super(QMainWindow, self).__init__(parent=parent) self.UI = Ui_MainWindow() self.UI.setupUi(self) self.add_to_log("OpenIMU - Prêt à travailler.", LogTypes.LOGTYPE_INFO) startWindow = StartWindow() if startWindow.exec() == QDialog.Rejected: # User closed the dialog - exits! exit(0) # Init database manager self.currentFileName = startWindow.fileName self.dbMan = DBManager(self.currentFileName) # Setup signals and slots self.setup_signals() # Maximize window self.showMaximized() # Load data self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO) self.currentDataSet = self.dbMan.get_dataset() self.load_data_from_dataset() self.UI.treeDataSet.setCurrentItem(None) # self.loadDemoData() self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE) # If we need to import data, show the import dialog if startWindow.importing: self.importRequested() def setup_signals(self): self.UI.treeDataSet.itemClicked.connect(self.tree_item_clicked) self.UI.btnDataSetInfos.clicked.connect(self.infosRequested) self.UI.btnAddGroup.clicked.connect(self.newGroupRequested) self.UI.btnAddParticipant.clicked.connect(self.newParticipantRequested) self.UI.treeDataSet.participantDragged.connect( self.participant_was_dragged) self.UI.btnDelete.clicked.connect(self.delete_requested) self.UI.btnImport.clicked.connect(self.importRequested) def load_data_from_dataset(self): self.UI.treeDataSet.clear() # Groups groups = self.dbMan.get_all_groups() for group in groups: self.UI.treeDataSet.update_group(group) # Participants participants = self.dbMan.get_all_participants() for participant in participants: self.UI.treeDataSet.update_participant(participant) # Recordsets recordsets = self.dbMan.get_all_recordsets() for recordset in recordsets: self.UI.treeDataSet.update_recordset(recordset) """def create_subrecord_item(self, name, id): item = QTreeWidgetItem() item.setText(0, name) item.setIcon(0, QIcon(':/OpenIMU/icons/subrecord.png')) item.setData(0, Qt.UserRole, id) item.setData(1, Qt.UserRole, 'subrecord') item.setFont(0, QFont('Helvetica', 12, QFont.Bold)) return item def create_sensor_item(self, name, id): item = QTreeWidgetItem() item.setText(0, name) item.setIcon(0, QIcon(':/OpenIMU/icons/sensor.png')) item.setData(0, Qt.UserRole, id) item.setData(1, Qt.UserRole, 'sensor') item.setFont(0, QFont('Helvetica', 12)) return item def create_result_item(self, name, id): item = QTreeWidgetItem() item.setText(0, name) item.setIcon(0, QIcon(':/OpenIMU/icons/result.png')) item.setData(0, Qt.UserRole, id) item.setData(1, Qt.UserRole, 'result') item.setFont(0, QFont('Helvetica', 12)) return item """ def update_group(self, group): item = self.UI.treeDataSet.update_group(group) self.UI.treeDataSet.setCurrentItem(item) def update_participant(self, participant): item = self.UI.treeDataSet.update_participant(participant) self.UI.treeDataSet.setCurrentItem(item) def clear_main_widgets(self): for i in reversed(range(self.UI.frmMain.layout().count())): self.UI.frmMain.layout().itemAt(i).widget().setParent(None) def show_group(self, group=None): self.clear_main_widgets() groupWidget = GroupWindow(dbManager=self.dbMan, group=group) self.UI.frmMain.layout().addWidget(groupWidget) groupWidget.dataSaved.connect(self.dataWasSaved) groupWidget.dataCancelled.connect(self.dataWasCancelled) def show_participant(self, participant=None, base_group=None): self.clear_main_widgets() partWidget = ParticipantWindow(dbManager=self.dbMan, participant=participant, default_group=base_group) self.UI.frmMain.layout().addWidget(partWidget) partWidget.dataSaved.connect(self.dataWasSaved) partWidget.dataCancelled.connect(self.dataWasCancelled) def add_to_log(self, text, log_type): format = "" if log_type == LogTypes.LOGTYPE_INFO: format = "<span style='color:black'>" if log_type == LogTypes.LOGTYPE_WARNING: format = "<span style='color:orange;font-style:italic'>" if log_type == LogTypes.LOGTYPE_ERROR: format = "<span style='color:red;font-weight:bold'>" if log_type == LogTypes.LOGTYPE_DEBUG: format = "<span style='color:grey;font-style:italic'>" if log_type == LogTypes.LOGTYPE_DONE: format = "<span style='color:green;font-weight:bold'>" self.UI.txtLog.append("<span style='color:grey'>" + datetime.now().strftime("%H:%M:%S.%f") + " </span>" + format + text + "</span>") self.UI.txtLog.ensureCursorVisible() def get_current_widget_data_type(self): # TODO: checks! return self.UI.frmMain.layout().itemAt(0).widget().data_type ###################### @pyqtSlot(QUrl) def urlChanged(self, url): print('url: ', url) @pyqtSlot() def importRequested(self): importer = ImportBrowser(dataManager=self.dbMan) if importer.exec() == QDialog.Accepted: self.load_data_from_dataset() @pyqtSlot() def infosRequested(self): infosWindow = ImportWindow(dataset=self.currentDataSet, filename=self.currentFileName) infosWindow.noImportUI = True infosWindow.infosOnly = True if infosWindow.exec() != QDialog.Rejected: # TODO: Save data self.currentDataSet.name = infosWindow.dataSet.name @pyqtSlot() def newGroupRequested(self): self.show_group() @pyqtSlot() def newParticipantRequested(self): # Check if we can get a root item (group) for the current selected item or not item = self.UI.treeDataSet.currentItem() if item is not None: while item.parent() is not None: item = item.parent() default_group = None if self.UI.treeDataSet.get_item_type(item) == "group": default_group = self.UI.treeDataSet.groups[ self.UI.treeDataSet.get_item_id(item)] self.show_participant(base_group=default_group) @pyqtSlot(Participant) def participant_was_dragged(self, participant): self.dbMan.update_participant(participant) self.update_participant(participant) @pyqtSlot(QTreeWidgetItem, int) def tree_item_clicked(self, item, column): # print(item.text(column)) item_id = self.UI.treeDataSet.get_item_id(item) item_type = self.UI.treeDataSet.get_item_type(item) # Clear all widgets self.clear_main_widgets() if item_type == "group": self.show_group(self.UI.treeDataSet.groups[item_id]) # groupWidget = GroupWindow(dbManager=self.dbMan, group = self.UI.treeDataSet.groups[item_id]) # self.UI.frmMain.layout().addWidget(groupWidget) if item_type == "participant": self.show_participant(self.UI.treeDataSet.participants[item_id]) if item_type == "recordsets" or item_type == "recordset" or item_type == "subrecord": if item_type == "recordsets": part = self.UI.treeDataSet.participants[ self.UI.treeDataSet.get_item_id(item.parent())] records = self.dbMan.get_all_recordsets(part) else: records = [self.UI.treeDataSet.recordsets[item_id]] recordsWidget = RecordsetWindow(manager=self.dbMan, recordset=records) self.UI.frmMain.layout().addWidget(recordsWidget) if item_type == "result": resultWidget = ResultWindow() self.UI.frmMain.layout().addWidget(resultWidget) self.UI.frmMain.update() @pyqtSlot() def dataWasSaved(self): item_type = self.get_current_widget_data_type() if item_type == "group": group = self.UI.frmMain.layout().itemAt(0).widget().group self.update_group(group) self.add_to_log("Groupe " + group.name + " mis à jour.", LogTypes.LOGTYPE_DONE) if item_type == "participant": part = self.UI.frmMain.layout().itemAt(0).widget().participant self.update_participant(part) self.add_to_log("Participant " + part.name + " mis à jour.", LogTypes.LOGTYPE_DONE) @pyqtSlot() def dataWasCancelled(self): item_type = self.get_current_widget_data_type() if item_type == "group": if self.UI.frmMain.layout().itemAt(0).widget().group is None: self.clear_main_widgets() if item_type == "participant": if self.UI.frmMain.layout().itemAt(0).widget().participant is None: self.clear_main_widgets() @pyqtSlot() def delete_requested(self): item_id = self.UI.treeDataSet.get_item_id( self.UI.treeDataSet.currentItem()) item_type = self.UI.treeDataSet.get_item_type( self.UI.treeDataSet.currentItem()) if item_type == "recordsets" or item_type == "results": return msg = QMessageBox() msg.setIcon(QMessageBox.Question) msg.setText("Désirez-vous vraiment supprimer " + self.UI.treeDataSet.currentItem().text(0) + " et tous les éléments associés?") msg.setWindowTitle("Confirmation de suppression") msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rval = msg.exec() if rval == QMessageBox.Yes: item_name = self.UI.treeDataSet.currentItem().text(0) if item_type == "group": group = self.UI.treeDataSet.groups[item_id] self.dbMan.delete_group(group) self.UI.treeDataSet.remove_group(group) if item_type == "participant": part = self.UI.treeDataSet.participants[item_id] self.dbMan.delete_participant(part) self.UI.treeDataSet.remove_participant(part) if item_type == "recordset": recordset = self.UI.treeDataSet.recordsets[item_id] self.dbMan.delete_recordset(recordset) self.UI.treeDataSet.remove_recordset(recordset) self.add_to_log(item_name + " a été supprimé.", LogTypes.LOGTYPE_DONE) self.clear_main_widgets() def closeEvent(self, event): print('closeEvent') """self.jupyter.stop() del self.jupyter self.jupyter = None """ def __del__(self): print('Done!') def create_chart_view(self, test_data=False): chart_view = IMUChartView(self) if test_data is True: chart_view.add_test_data() return chart_view
class ActigraphDBTest1(unittest.TestCase): @timing def setUp(self): np.set_printoptions(suppress=True) print(__file__ + ' Creating database') self.db = DBManager('actigraph.db', True, False) self.group = self.db.add_group('MyGroup', 'MyDescription') self.participant = self.db.add_participant(group=self.group, name='Anonymous', description='Participant') @timing def tearDown(self): self.db.commit() @timing def load_file(self, name='../resources/samples/test.gt3x'): print('loading file :', name) result = gt3x_importer(name) self.assertEqual(len(result), 2) return result def add_recordset_to_db(self, name, start_timestamp, stop_timestamp): recordset = self.db.add_recordset(self.participant, name, start_timestamp, stop_timestamp) return recordset def add_sensor_to_db(self, sensor_type, name, hw_name, location, sampling_rate, data_rate): # _id_sensor_type, _name, _hw_name, _location, _sampling_rate, _data_rate): sensor = self.db.add_sensor(sensor_type, name, hw_name, location, sampling_rate, data_rate) return sensor def add_channel_to_db(self, sensor, unit, data_format, label): channel = self.db.add_channel(sensor, unit, data_format, label) return channel def add_sensor_data_to_db(self, recordset, sensor, channel, timestamp, data): sensor_data = self.db.add_sensor_data(recordset, sensor, channel, timestamp, data) return sensor_data @timing def commit(self): return self.db.commit() @timing def flush(self): return self.db.flush() def test_import(self): # Return file info and data contents """ return [info, {'activity': activity_data, 'battery': battery_data, 'lux': lux_data, 'event': event_data, 'parameters': parameters_data, 'metadata': metadata_data }] """ [info, data] = self.load_file() self.assertTrue(len(info) > 0) self.assertTrue(len(data) == 6) print(info) # Creating recordset # print(info['Start Date'], info['Last Sample Time']) start = int(info['Start Date']) stop = int(info['Last Sample Time']) print(start, stop) start_timestamp = ticksconverter(start) end_timestamp = ticksconverter(stop) print(start_timestamp, end_timestamp) recordset = self.add_recordset_to_db(info['Subject Name'], start_timestamp, end_timestamp) print(recordset) if data.__contains__('activity'): print('activity found') # Create sensor accelerometer_sensor = self.add_sensor_to_db( SensorType.ACCELEROMETER, 'Accelerometer', info['Device Type'], 'Unknown', info['Sample Rate'], 1) accelerometer_channels = list() # Create channels accelerometer_channels.append( self.add_channel_to_db(accelerometer_sensor, Units.GRAVITY_G, DataFormat.FLOAT32, 'Accelerometer_Y')) accelerometer_channels.append( self.add_channel_to_db(accelerometer_sensor, Units.GRAVITY_G, DataFormat.FLOAT32, 'Accelerometer_X')) accelerometer_channels.append( self.add_channel_to_db(accelerometer_sensor, Units.GRAVITY_G, DataFormat.FLOAT32, 'Accelerometer_Z')) # Should be 1970, epoch last_timestamp = 0 all_timestamps = [] value_dict = {} # Import data for epoch in data['activity']: # An epoch will contain a timestamp and array with each acc_x, acc_y, acc_z self.assertEqual(len(epoch), 2) current_timestamp = epoch[0] # print('current_timestamp', current_timestamp, current_timestamp == (last_timestamp + 1)) # Check for consecutive timestamps create_array = current_timestamp != (last_timestamp + 1) # Do not allow more than one hour of consecutive data if create_array is not True: if current_timestamp - all_timestamps[-1] >= 3600: create_array = True # Consecutive timestamps? if create_array is True: all_timestamps.append(current_timestamp) # Create list for all values for this timestamp value_dict[current_timestamp] = [list(), list(), list()] # Get data samples = epoch[1] # Separate write for each channel for index in range(0, len(accelerometer_channels)): # Using last timestamp to append data value_dict[all_timestamps[-1]][index].append( samples[:, index]) # Update timestamp last_timestamp = current_timestamp # Insert into DB as chunks of data # print('should insert records count: ', len(all_timestamps)) # print('should insert data count:', len(value_dict)) for timestamp in all_timestamps: for index in range(0, len(value_dict[timestamp])): # print(index, timestamp, len(value_dict[timestamp][index])) vector = np.concatenate(value_dict[timestamp][index]) # print('vector: ', len(vector), vector.shape, vector.dtype) if len(vector) > 0: self.add_sensor_data_to_db( recordset, accelerometer_sensor, accelerometer_channels[index], datetime.datetime.fromtimestamp(timestamp), vector) # Flush DB self.flush() if data.__contains__('battery'): print('battery found') # Create sensor volt_sensor = self.add_sensor_to_db(SensorType.BATTERY, 'Battery', info['Device Type'], 'Unknown', 0, 1) # Create channel volt_channel = self.add_channel_to_db(volt_sensor, Units.VOLTS, DataFormat.FLOAT32, 'Battery') for epoch in data['battery']: timestamp = datetime.datetime.fromtimestamp(epoch[0]) value = np.float32(epoch[1]) self.assertEqual(len(value.tobytes()), 4) self.add_sensor_data_to_db(recordset, volt_sensor, volt_channel, timestamp, value) # Flush to DB (ram) self.flush() if data.__contains__('lux'): print('lux found') # Create sensor lux_sensor = self.add_sensor_to_db(SensorType.LUX, 'Lux', info['Device Type'], 'Unknown', 1, 1) # Create channel lux_channel = self.add_channel_to_db(lux_sensor, Units.LUX, DataFormat.FLOAT32, 'Lux') for epoch in data['lux']: timestamp = datetime.datetime.fromtimestamp(epoch[0]) value = np.float32(epoch[1]) self.assertEqual(len(value.tobytes()), 4) self.add_sensor_data_to_db(recordset, lux_sensor, lux_channel, timestamp, value) # Flush to DB (ram) self.flush() # Write data to file self.commit() @timing def read_back_data(self, participant): recordsets = self.db.get_all_recordsets(participant) print(recordsets) for record in recordsets: alldata = self.db.get_all_sensor_data(record) print('recordset size', len(alldata)) for data in alldata: print('type', type(data.data)) break def test_reload_from_db(self): # Import data first self.test_import() self.read_back_data(self.participant)