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
Example #2
0
    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)
Example #4
0
    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)
Example #6
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,
Example #7
0
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()
Example #8
0
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)