def test_write_read_stats_over_samples_offset(self): fh = self._create_file(0, 2) r = DataReader() r.raw_processor.suppress_mode = 'off' r.open(fh) data = r.data_get(7, 50, 10) np.testing.assert_allclose(np.arange(23, 90, 20), data[:, 0]['mean'])
def test_create_single(self): fh = self._create_file_insert(0, 2, 2) r = DataReader() r.raw_processor.suppress_mode = 'off' r.open(fh) self.assertEqual([0, 252], r.sample_id_range) self.assertEqual(1000, r.output_sampling_frequency) self.assertEqual(0.05, r.reduction_frequency) self.assertEqual(0.252, r.duration) self.assertEqual(0.0, r.sample_id_to_time(0)) self.assertEqual(0, r.time_to_sample_id(0)) self.assertEqual(0.2, r.sample_id_to_time(200)) self.assertEqual(200, r.time_to_sample_id(0.2)) data = r.data_get(6, 10, 1) np.testing.assert_allclose(np.arange(12, 20, 2), data[:, 0]['mean'])
def run(): args = get_parser().parse_args() reader = DataReader() reader.open(args.infile) s_min, s_max = reader.sample_id_range sample_count = s_max - s_min writer = DataRecorder(args.outfile, reader.calibration, reader.user_data) block_size = int(reader.sampling_frequency) print(f'samples={sample_count}, fs={reader.sampling_frequency}') block_count = (sample_count + block_size - 1) // block_size for block in range(block_count): offset = block * block_size offset_next = offset + block_size if offset_next > sample_count: offset_next = sample_count data = reader.samples_get(offset, offset_next, 'samples') writer.insert(data) progress(block, block_count - 1) reader.close() writer.close() return 0
class RecordingViewerDevice: """A user-interface-compatible device that displays previous recorded data :param filename: The filename path to the pre-recorded data. """ def __init__(self, filename, current_ranging_format=None): if isinstance(filename, str) and not os.path.isfile(filename): raise IOError('file not found') self._filename = filename self._current_ranging_format = current_ranging_format self._reader = None self._views = [] self._coalesce = {} self._thread = None self._cmd_queue = queue.Queue() # tuples of (command, args, callback) self._response_queue = queue.Queue() self._quit = False self._log = logging.getLogger(__name__) def __str__(self): return os.path.basename(self._filename) @property def sampling_frequency(self): if self._reader is None: return None return self._reader.sampling_frequency @property def calibration(self): if self._reader is None: return None return self._reader.calibration @property def voltage_range(self): return self._reader.voltage_range def _cmd_process(self, cmd, view, args, cbk): rv = None try: # self._log.debug('_cmd_process %s - start', cmd) if cmd == 'refresh': view._refresh_requested = True elif cmd == 'on_x_change': rv = view._on_x_change(*args) elif cmd == 'samples_get': rv = view._samples_get(**args) elif cmd == 'statistics_get': rv = view._statistics_get(**args) elif cmd == 'statistics_get_multiple': rv = view._statistics_get_multiple(**args) elif cmd == 'view_factory': self._views.append(args) rv = args elif cmd == 'view_close': if args in self._views: self._views.remove(args) elif cmd == 'open': rv = self._open() elif cmd == 'close': rv = self._close() elif cmd == 'ping': rv = args else: self._log.warning('unsupported command %s', cmd) except: self._log.exception('While running command') if callable(cbk): try: cbk(rv) except: self._log.exception('in callback') def run(self): cmd_count = 0 timeout = 1.0 self._log.info('RecordingViewerDevice.start') while not self._quit: try: cmd, view, args, cbk = self._cmd_queue.get(timeout=timeout) except queue.Empty: timeout = 1.0 for value in self._coalesce.values(): self._cmd_process(*value) self._coalesce.clear() for view in self._views: if view._refresh_requested: view._update() cmd_count = 0 continue cmd_count += 1 timeout = 0.0 try: source_id = args.pop('source_id') except: source_id = None if source_id is not None: key = f'{view}_{cmd}_{source_id}' # keep most recent only self._coalesce[key] = (cmd, view, args, cbk) else: self._cmd_process(cmd, view, args, cbk) self._log.info('RecordingViewerDevice.run done') def _post(self, command, view=None, args=None, cbk=None): if self._thread is None: self._log.info('RecordingViewerDevice._post(%s) when thread not running', command) else: self._cmd_queue.put((command, view, args, cbk)) def _post_block(self, command, view=None, args=None, timeout=None): timeout = TIMEOUT if timeout is None else float(timeout) # self._log.debug('_post_block %s start', command) while not self._response_queue.empty(): self._log.warning('response queue not empty') try: self._response_queue.get(timeout=0.0) except queue.Empty: pass if self._thread is None: raise IOError('View thread not running') self._post(command, view, args, lambda rv_=None: self._response_queue.put(rv_)) try: rv = self._response_queue.get(timeout=timeout) except queue.Empty as ex: self._log.error('RecordingViewerDevice thread hung: %s - FORCE CLOSE', command) self._post('close', None, None) self._thread.join(timeout=TIMEOUT) self._thread = None rv = ex except Exception as ex: rv = ex if isinstance(rv, Exception): raise IOError(rv) # self._log.debug('_post_block %s done', command) # rv return rv def _open(self): self._reader = DataReader() if self._current_ranging_format is not None: self._reader.raw_processor.suppress_mode = self._current_ranging_format self._reader.open(self._filename) # todo progress bar updates self._log.info('RecordingViewerDevice.open') def _close(self): if self._reader is not None: self._reader.close() self._reader = None self._quit = True def view_factory(self): view = RecordingView(self) return self._post_block('view_factory', None, view) def open(self, event_callback_fn=None): self.close() self._log.info('open') self._thread = threading.Thread(name='view', target=self.run) self._thread.start() self._post_block('open') def close(self): if self._thread is not None: self._log.info('close') try: self._post_block('close') except Exception: self._log.exception('while attempting to close') self._thread.join(timeout=TIMEOUT) self._thread = None