示例#1
0
    def test_get_data_for_clock(self):
        """Test queries to the data store by experiment clock units."""

        channels = ['ch1', 'ch2', 'TRG']
        sample_hz = 100
        trigger_at = 10
        num_records = 1000
        n_channels = len(channels) - 1
        data = [
            mock_record(n_channels) + [0 if (i + 1) < trigger_at else 1]
            for i in range(num_records)
        ]

        device = _MockConnector(data=data,
                                device_spec=DeviceSpec(name="Mock_device",
                                                       channels=channels,
                                                       sample_rate=sample_hz))
        daq = DataAcquisitionClient(
            connector=device,
            buffer_name='buffer_client_test_get_data_for_clock.db',
            raw_data_file_name=None,
            delete_archive=True,
            clock=CountClock())

        daq.start_acquisition()
        time.sleep(0.2)
        daq.stop_acquisition()

        self.assertTrue(daq.is_calibrated)

        # rownum at calibration should be trigger_at
        self.assertEqual(trigger_at, daq.record_at_calib.rownum)
        self.assertEqual(trigger_at, daq.record_at_calib.timestamp)
        self.assertEqual(data[trigger_at - 1], daq.record_at_calib.data)

        # Test with clocks exactly synchronized.
        self.assertEqual(0.1, daq.offset)
        data_slice = daq.get_data_for_clock(calib_time=0.1,
                                            start_time=0.2,
                                            end_time=0.3)
        self.assertEqual(10, len(data_slice))

        start_offset = 20
        for i, record in enumerate(data_slice):
            # mock-data is 0-based, so we have to subtract 1 from the start.
            mock_data_index = i + start_offset - 1
            self.assertEqual(record.data, data[mock_data_index])

        # Test with clocks offset
        data_slice = daq.get_data_for_clock(calib_time=0.2,
                                            start_time=0.4,
                                            end_time=0.6)
        self.assertEqual(20, len(data_slice))
        start_offset = 30
        for i, record in enumerate(data_slice):
            # mock-data is 0-based, so we have to subtract 1 from the start.
            mock_data_index = i + start_offset - 1
            self.assertEqual(record.data, data[mock_data_index])

        daq.cleanup()
示例#2
0
 def __init__(self, *args, **kwargs):
     super(TestLslDevice, self).__init__(*args, **kwargs)
     self.server = None
     self.device_spec = DeviceSpec(
         name='LSL',
         channels=['C3', 'C4', 'Cz', 'FPz', 'POz', 'CPz', 'O1', 'O2'],
         sample_rate=100)
示例#3
0
    def test_zero_offset(self):
        """Test offset value override"""

        channels = ['ch1', 'ch2', 'TRG']
        sample_hz = 100
        trigger_at = 10
        num_records = 500
        n_channels = len(channels) - 1

        data = [
            mock_record(n_channels) + [0 if (i + 1) < trigger_at else 1]
            for i in range(num_records)
        ]

        device = _MockConnector(data=data,
                                device_spec=DeviceSpec(name="Mock_device",
                                                       channels=channels,
                                                       sample_rate=sample_hz))
        daq = DataAcquisitionClient(connector=device,
                                    buffer_name='buffer_client_test_offset.db',
                                    raw_data_file_name=None,
                                    delete_archive=True,
                                    clock=CountClock())

        daq.is_calibrated = True  # force the override.
        daq.start_acquisition()
        time.sleep(0.1)
        daq.stop_acquisition()

        self.assertTrue(daq.is_calibrated)
        self.assertEqual(
            daq.offset, 0.0, "Setting the is_calibrated to True\
            should override the offset calcution.")

        daq.cleanup()
示例#4
0
    def test_missing_offset(self):
        """Test missing offset when no triggers are present in the data."""
        channels = ['ch1', 'ch2', 'TRG']
        sample_hz = 100
        num_records = 500

        # mock_data only has empty trigger values.
        n_channels = len(channels) - 1
        data = [mock_record(n_channels) + [0] for i in range(num_records)]

        device = _MockConnector(data=data,
                                device_spec=DeviceSpec(name="Mock_device",
                                                       channels=channels,
                                                       sample_rate=sample_hz))
        daq = DataAcquisitionClient(
            connector=device,
            clock=CountClock(),
            buffer_name='buffer_client_test_missing_offset.db',
            raw_data_file_name=None,
            delete_archive=True)

        with daq:
            time.sleep(0.1)

        self.assertFalse(daq.is_calibrated)
        self.assertEqual(daq.offset, None)
        daq.cleanup()
示例#5
0
    def test_offset(self):
        """Test offset calculation"""

        channels = ['ch1', 'ch2', 'TRG']
        sample_hz = 100
        trigger_at = 10
        num_records = 500
        n_channels = len(channels) - 1

        data = [
            mock_record(n_channels) + [0 if (i + 1) < trigger_at else 1]
            for i in range(num_records)
        ]

        device = _MockConnector(data=data,
                                device_spec=DeviceSpec(name="Mock_device",
                                                       channels=channels,
                                                       sample_rate=sample_hz))
        daq = DataAcquisitionClient(connector=device,
                                    buffer_name='buffer_client_test_offset.db',
                                    raw_data_file_name=None,
                                    delete_archive=True,
                                    clock=CountClock())

        daq.start_acquisition()
        time.sleep(0.1)
        daq.stop_acquisition()

        # The assertions should work before the stop_acquisition, but on some
        # Windows environments the tests were taking too long to setup and the
        # time would complete before any data had been processed.
        self.assertTrue(daq.is_calibrated)
        self.assertEqual(daq.offset, float(trigger_at) / sample_hz)

        daq.cleanup()
示例#6
0
 def __init__(self, *args, **kwargs):
     super(TestLslChannelConfig, self).__init__(*args, **kwargs)
     self.device_spec = DeviceSpec(name='DSI',
                                   channels=[
                                       'C3', 'C4', 'Cz', 'FPz', 'POz',
                                       'CPz', 'O1', 'O2', 'TRG'
                                   ],
                                   sample_rate=300)
示例#7
0
def spec(name=DEVICE_NAME,
         channels=DEVICE_CHANNELS,
         sample_rate=DEVICE_SAMPLE_RATE):
    """Creates a DeviceSpec for testing purposes"""
    return DeviceSpec(name=name,
                      channels=channels,
                      sample_rate=sample_rate,
                      connection_methods=[ConnectionMethod.TCP])
示例#8
0
 def __init__(self, *args, **kwargs):
     super(TestDataAcquisitionClient, self).__init__(*args, **kwargs)
     num_channels = 25
     num_records = 500
     self.device_spec = DeviceSpec(
         name="Mock_device",
         channels=['ch' + str(i) for i in range(num_channels)],
         sample_rate=300.0)
     self.mock_data = list(mock_data(num_records, num_channels))
示例#9
0
    def test_connect(self):
        """Should require a connect call before initialization."""
        device = LslConnector(connection_params={},
                              device_spec=DeviceSpec(
                                  name='LSL',
                                  channels=self.channels,
                                  sample_rate=self.sample_rate))

        with pytest.raises(Exception):
            device.acquisition_init()
示例#10
0
    def test_device_info_channels(self):
        """Device should list the correct channels"""
        spec = DeviceSpec(name='LSL',
                          channels=self.channels,
                          sample_rate=self.sample_rate)
        device = LslConnector(connection_params={}, device_spec=spec)
        device.connect()
        device.acquisition_init()

        self.assertEqual(self.channels, device.channels)
示例#11
0
    def test_incorrect_frequency(self):
        """Provided sample_rate should match sample rate read from device"""
        device = LslConnector(connection_params={},
                              device_spec=DeviceSpec(name='LSL',
                                                     channels=self.channels,
                                                     sample_rate=300))

        device.connect()

        with pytest.raises(Exception):
            device.acquisition_init()
示例#12
0
 def test_encoder(self):
     """It should encode array data that can be subsequently decoded."""
     device_spec = DeviceSpec(
         name="DSI-VR300",
         channels=["P4", "Fz", "Pz", "F7", "PO8", "PO7", "Oz", "TRG"],
         sample_rate=300.0)
     protocol = DsiProtocol(device_spec)
     data = [float(i) for i in range(device_spec.channel_count)]
     encoded = protocol.encode(data)
     parsed = dsi.packet.parse(encoded)
     self.assertEqual(parsed.type, 'EEG_DATA')
     self.assertEqual(parsed.sensor_data, data)
示例#13
0
    def test_incorrect_number_of_channels(self):
        """A list of channels with len that does not match channel_count should
        raise an exception."""

        spec = DeviceSpec(name='LSL',
                          channels=['ch1', 'ch2'],
                          sample_rate=self.sample_rate)
        device = LslConnector(connection_params={}, device_spec=spec)
        self.assertEqual(spec.channel_count, 2)
        self.assertNotEqual(len(device.channels), self.channel_count)
        device.connect()

        with pytest.raises(Exception):
            device.acquisition_init()
示例#14
0
    def test_read_data(self):
        """Should produce a valid data record."""
        print(self.device_spec.channels)
        device = LslConnector(connection_params={},
                              device_spec=DeviceSpec(
                                  name='LSL',
                                  channels=self.channels,
                                  sample_rate=self.sample_rate))
        device.connect()
        device.acquisition_init()
        data = device.read_data()

        self.assertTrue(len(data) > 0)
        self.assertEqual(len(data), len(device.channels))

        for channel in data[0:-1]:
            self.assertTrue(isinstance(channel, float))
示例#15
0
    def test_protocol_init_messages(self):
        """Should have the channels and the sample_rate."""
        device_spec = DeviceSpec(
            name="DSI-VR300",
            channels=["P4", "Fz", "Pz", "F7", "PO8", "PO7", "Oz", "TRG"],
            sample_rate=300.0)
        protocol = DsiProtocol(device_spec)
        init_messages = protocol.init_messages()
        channel_msg = init_messages[0]
        parsed1 = dsi.packet.parse(channel_msg)
        self.assertEqual(parsed1.type, 'EVENT')
        self.assertEqual(parsed1.event_code, 'SENSOR_MAP')
        self.assertEqual(parsed1.message, ','.join(device_spec.channels))

        parsed2 = dsi.packet.parse(init_messages[1])
        self.assertEqual(parsed2.type, 'EVENT')
        self.assertEqual(parsed2.event_code, 'DATA_RATE')
        self.assertEqual(parsed2.message, u',300')
def main(debug: bool = False):
    # pylint: disable=too-many-locals
    """Creates a sample lsl client that reads data from a sample TCP server
    (see demo/server.py). Data is written to a rawdata.csv file, as well as a
    buffer.db sqlite3 database. These files are written in whichever directory
    the script was run.

    The client/server can be stopped with a Keyboard Interrupt (Ctl-C)."""

    import time
    import sys

    # Allow the script to be run from the bci root, acquisition dir, or
    # demo dir.
    sys.path.append('.')
    sys.path.append('..')
    sys.path.append('../..')

    from bcipy.acquisition.devices import DeviceSpec
    from bcipy.acquisition.protocols.lsl.lsl_connector import LslConnector
    from bcipy.acquisition.client import DataAcquisitionClient
    from bcipy.acquisition.datastream.lsl_server import LslDataServer
    from bcipy.acquisition.datastream.tcp_server import await_start

    from bcipy.helpers.system_utils import log_to_stdout

    if debug:
        log_to_stdout()

    # Generic LSL device with 16 channels.
    device_spec = DeviceSpec(name="LSL_demo",
                             channels=[
                                 "Ch1", "Ch2", "Ch3", "Ch4", "Ch5", "Ch6",
                                 "Ch7", "Ch8", "Ch9", "Ch10", "Ch11", "Ch12",
                                 "Ch13", "Ch14", "Ch15", "Ch16"
                             ],
                             sample_rate=256.0)
    server = LslDataServer(device_spec=device_spec)
    await_start(server)

    # Device is for reading data.
    connector = LslConnector(connection_params={}, device_spec=device_spec)

    raw_data_name = 'demo_raw_data.csv'
    client = DataAcquisitionClient(connector=connector,
                                   raw_data_file_name=raw_data_name)

    try:
        client.start_acquisition()

        print("\nCollecting data for 3s... (Interrupt [Ctl-C] to stop)\n")

        while True:
            time.sleep(1)
            client.marker_writer.push_marker('calibration_trigger')
            time.sleep(2)
            # since calibration trigger was pushed after 1 second of sleep
            print(f"Offset: {client.offset}; this value should be close to 1.")
            client.stop_acquisition()
            client.cleanup()
            server.stop()
            print(f"\nThe collected data has been written to {raw_data_name}")
            break

    except KeyboardInterrupt:
        print("Keyboard Interrupt; stopping.")
        client.stop_acquisition()
        client.cleanup()
        server.stop()
        print(f"\nThe collected data has been written to {raw_data_name}")