def __init__(self): super(ResultSaver, self).__init__() self._stop = subject.Subject() self.config = config.SettingAccessor(self.config_prefix) self.subjects: Subjects = services.service_provider.SubjectProvider().get_or_create_instance(None) self.saving_scheduler = scheduler.NewThreadScheduler() self.subjects.image_producer.pipe( operators.observe_on(self.saving_scheduler), operators.filter(self.config_enabled_filter("save_images")), operators.take_until(self._stop), ).subscribe(ErrorToConsoleObserver(self.save_image)) self.subjects.detection_result.pipe( operators.observe_on(self.saving_scheduler), operators.filter(self.config_enabled_filter("save_labels")), operators.take_until(self._stop), ).subscribe(ErrorToConsoleObserver(self.save_labels)) self.subjects.add_to_timeline.pipe( operators.observe_on(self.saving_scheduler), operators.filter(self.config_enabled_filter("save_events")), operators.take_until(self._stop), ).subscribe(ErrorToConsoleObserver(self.save_timeline_events)) config.setting_updated_channel.pipe( operators.filter(self._directory_filter), operators.take_until(self._stop), ).subscribe(ErrorToConsoleObserver(lambda x: self.initialize_saving_directory())) self.initialize_saving_directory()
def __init__(self, protocol): # See comment in players.py. self._aio_scheduler = QtScheduler(QtCore) messages = protocol.register("game_info") self.new = messages.pipe( ops.flat_map(self._split_game_info), ops.observe_on(self._aio_scheduler), ops.flat_map(self._process_game), ops.observe_on(ImmediateScheduler()), ops.filter(lambda x: x is not None), )
def light_state_equals(light_id: str, light_final_state: str, test_context: Data.TestContext, loop: asyncio.AbstractEventLoop, awaitables: List[RxObservable]): assert isinstance(light_id, str) assert isinstance(light_final_state, str) def take_while_state(payload: Structs.s_lights_state) -> bool: return payload.newState != light_final_state timeout_sec = 10.0 lightbulb: Data.Lightbulb = test_context.lightbulbs[light_id] observable: RxObservable = lightbulb.light_state.pipe( RxOp.timeout(timeout_sec), RxOp.observe_on(scheduler=AsyncIOScheduler(loop)), RxOp.take_while(take_while_state, inclusive=True), ) observable.subscribe(on_next=lambda i: print(f"on_next: {i}"), on_error=lambda e: print(f"on_error: {e}"), on_completed=lambda: print("on_completed"), scheduler=AsyncIOScheduler(loop)) awaitables.append(observable)
def onClicked(): xs = rx.from_([1, 2, 3, 4, 5]) xs.pipe( ops.map(bgAlg), ops.subscribe_on(thread_pool), ops.observe_on(gui_scheduler), ).subscribe(addLabel)
def main(): loop = asyncio.get_event_loop() io_scheduler = AsyncIOThreadSafeScheduler(loop=loop) scheduler = ThreadPoolScheduler(multiprocessing.cpu_count()) video_stream_observable = rx.using( lambda: VideoStreamDisposable(), lambda d: rx.from_iterable(video_stream_iterable(d.cap))) disposable = video_stream_observable.pipe( ops.subscribe_on(scheduler), ops.sample(1 / ARGS.fps), # sample frames based on fps ops.filter(has_face), # filter frames without faces ops.map(lambda frame: Image.fromarray( cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))), # map frame to PIL image ops.observe_on(io_scheduler), ops.map(lambda img: ImageFacesPair(img, analyse_frame(img)) ), # analyse faces on frame ops.filter( lambda img_faces_pair: any([ face.top_prediction.confidence >= ARGS.min_confidence and face. top_prediction.confidence <= ARGS.max_confidence for face in img_faces_pair.faces ]) ), # proceed only if min_confidence <= person_confidence <= max_confidence ops.do_action(on_next=save_frame)).subscribe( on_error=lambda e: logger.exception(e)) try: loop.run_forever() except Exception as e: logger.exception(e) logger.info("Data collector shutdown") disposable.dispose()
def start(self): if not self.subjects.analyzer_connected.value: if not self.analyzer_not_connected_prompt(): return qt_scheduler = QtScheduler(QtCore) # this sequence is auto-back-pressured observable = self.request_media_file(qt_scheduler).pipe( # list of files operators.observe_on(scheduler.NewThreadScheduler()), # The following sequence will be run on a new thread. operators.flat_map(rx.from_list), # observable of files. self.load_file_operator( ), # When back pressure, this one will block. # observable of frames (AcquiredImage). This operation will be blocked if the downstream is blocked. operators.take_until(self._stop), ).subscribe( ErrorToConsoleObserver(on_next=self.next_image, on_error=self._catch)) self.subjects.analyzer_back_pressure_detected.pipe( operators.take_until(self._stop), ).subscribe( self.notify_back_pressure_changed) super().start()
def _get_devices(self) -> None: self._composite_disposable.add( self._x52_driver_interactor.get_devices().pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._handle_get_devices_result, on_error=self._handle_get_devices_result))
def __init__( self, influxdb_client, write_options: WriteOptions = WriteOptions()) -> None: self._influxdb_client = influxdb_client self._write_service = WriteService(influxdb_client.api_client) self._write_options = write_options if self._write_options.write_type is WriteType.batching: # Define Subject that listen incoming data and produces writes into InfluxDB self._subject = Subject() # Define a scheduler that is used for processing incoming data - default singleton observable = self._subject.pipe( ops.observe_on(self._write_options.write_scheduler)) self._disposable = observable \ .pipe( # Split incoming data to windows by batch_size or flush_interval ops.window_with_time_or_count(count=write_options.batch_size, timespan=timedelta(milliseconds=write_options.flush_interval)), # Map incoming batch window in groups defined by 'organization', 'bucket' and 'precision' ops.flat_map(lambda v: _window_to_group(v)), # Write data into InfluxDB (possibility to retry if its fail) ops.map(mapper=lambda batch: self._retryable(data=batch, delay=self._jitter_delay())), # ops.merge_all()) \ .subscribe(self._on_next, self._on_error, self._on_complete) else: self._subject = None self._disposable = None
def __init__(self, protocol): # We use this scheduler so that we don't handle all player messages at # the same time at startup, as this hangs the UI for a few seconds. # With this, it's just a minor slowdown. # # One side effect is that games and players don't appear immediately # (as in, UI is available before they're all shown). This shouldn't be # a problem. self._aio_scheduler = QtScheduler(QtCore) messages = protocol.register("player_info") self.new = messages.pipe( ops.flat_map(self._split_player_info), ops.observe_on(self._aio_scheduler), ops.flat_map(self._handle_player_info), ops.observe_on(ImmediateScheduler()), )
def __init__(self, concurrency_per_group, delay_seconds=0, description=None): self._queue = Subject() self._description = description self.request_scheduler = ThreadPoolScheduler(concurrency_per_group) producer_scheduler = ThreadPoolScheduler(concurrency_per_group) def on_next(result): output = result['output'] output.on_next({ 'value': result.get('value'), 'completed': result.get('completed') }) self._subscription = self._queue.pipe( observe_on(producer_scheduler), group_by(lambda r: r['group']), flat_map(lambda concurrency_group: concurrency_group.pipe( map(lambda r: r['work']), delay(delay_seconds), merge(max_concurrent=concurrency_per_group), merge_all(), )), take_until_disposed()).subscribe( on_next=on_next, on_error=lambda error: logging.exception( 'Error in {} request stream'.format(self)), scheduler=producer_scheduler)
def _check_new_version(self) -> None: self._composite_disposable.add( self._check_new_version_interactor.execute().pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._handle_new_version_response, on_error=lambda e: _LOG.exception( "Check new version error: %s", str(e))))
def set_grpc_observable(self, new_observable: Observable, **kw): new_observable = observe_on(ThreadPoolScheduler(1))(new_observable) method_name = self._get_method_name(**kw) if method_name not in self._observable_to_be_subscribed: _LOGGER.exception('Method name {} not found, kw: {}'.format(method_name, kw)) raise KeyError self.observables[method_name] = new_observable self._observable_to_be_subscribed[method_name] = new_observable
def on_power_limit_apply_button_clicked(self, *_: Any) -> None: self._composite_disposable.add( self._set_power_limit_interactor.execute( *self.main_view.get_power_limit()).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._handle_set_power_limit_result, on_error=self._handle_set_power_limit_result))
def test_with_observe_on(self): self.source.pipe( operators.do_action(lambda x: print(f"Producing {x}")), operators.observe_on(NewThreadScheduler()), operators.map(self.slow_op), operators.do_action(self.stop), operators.take_until(self._stop), ).run()
def _update_mfd_button_line(self, text: str) -> None: _LOG.debug("update_mfd_button_line") self._composite_disposable.add( self._x52_driver_interactor.set_mfd_button_line( self._driver_list[self._driver_index], text).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_error=lambda e: self._handle_generic_set_result( e, "MFD Button")))
def _monitor_evdev_events(self) -> None: _LOG.error("monitor_evdev_events") self._composite_disposable.add( self._x52_driver_interactor.get_evdev_events( self._driver_list[self._driver_index]).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._on_evdev_event, on_error=lambda e: self._handle_generic_set_result( e, "Evdev events")))
def _update_mfd_profile_name(self, name: str, clear_mfd: bool = False) -> None: self._composite_disposable.add( self._x52_driver_interactor.set_mfd_profile_name_line( self._driver_list[self._driver_index], name, clear_mfd).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_error=lambda e: self._handle_generic_set_result( e, "MFD Profile name")))
def on_apply_offsets_button_clicked(self, *_: Any) -> None: self._composite_disposable.add( self._set_overclock_interactor.execute( self._gpu_index, self._overclock.perf_level_max, self.view.get_gpu_offset(), self.view.get_memory_offset()).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._handle_set_overclock_result, on_error=self._handle_set_overclock_result))
def _start_periodic_refresh(self) -> None: _LOG.debug("start refresh") self._composite_disposable.add( rx.interval(timedelta(milliseconds=999), scheduler=self._scheduler).pipe( operators.start_with(0), operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._on_periodic_refresh_tick, on_error=lambda e: _LOG.exception( f"Refresh error: {str(e)}")))
def __init__(self) -> None: self._subject = Subject() self._scheduler = ThreadPoolScheduler(max_workers=1) obs = self._subject.pipe(ops.observe_on(self._scheduler)) self._disposable = obs \ .pipe(ops.window_with_time_or_count(count=5, timespan=datetime.timedelta(milliseconds=10_000)), ops.flat_map(lambda x: self._window_to_group(x)), ops.map(mapper=lambda x: self._retryable(data=x, delay=self._jitter_delay(jitter_interval=1000))), ops.merge_all()) \ .subscribe(self._result, self._error, self._on_complete) pass
def _set_speed_profile(self, profile: SpeedProfile) -> None: observable = self._set_speed_profile_interactor \ .execute(profile.channel, self._get_profile_data(profile)) self._composite_disposable.add( observable.pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe( on_next=lambda _: self._update_current_speed_profile(profile), on_error=lambda e: self._on_set_speed_profile_error( e, profile)))
def configureObservers(self): qt_scheduler = QtScheduler(QtCore) subject_provider = service_provider.SubjectProvider() subjects: Subjects = subject_provider.get_or_create_instance(None) # display raw images self.subscriptions.add( subjects.image_producer.pipe( operators.observe_on(qt_scheduler), ).subscribe( ErrorToConsoleObserver( self.dockedPanels["input"].widget().updateImage))) # display processed images self.subscriptions.add( subjects.rendered_sample_image_producer.pipe( operators.observe_on(qt_scheduler), ).subscribe( ErrorToConsoleObserver( self.dockedPanels["processed"].widget().updateImage))) self.subscriptions.add( subjects.processed_distributions.pipe( operators.pluck_attr("dists"), operators.pluck("areas"), operators.observe_on(qt_scheduler), ).subscribe( ErrorToConsoleObserver( self.dockedPanels["areaDist"].widget().update_histogram))) self.subscriptions.add( subjects.processed_distributions.pipe( operators.pluck_attr("dists"), operators.pluck("ellipses"), operators.observe_on(qt_scheduler), ).subscribe( ErrorToConsoleObserver(self.dockedPanels["ellipseDist"].widget( ).update_histogram))) self.subscriptions.add( subjects.add_to_timeline.pipe( operators.observe_on(qt_scheduler)).subscribe( ErrorToConsoleObserver( self.dockedPanels["timeline"].widget().update_plot)))
def _start_refresh(self) -> None: _LOG.debug("start refresh") refresh_interval = self._settings_interactor.get_int( 'settings_refresh_interval') self._composite_disposable.add( rx.interval(refresh_interval, scheduler=self._scheduler).pipe( operators.start_with(0), operators.subscribe_on(self._scheduler), operators.flat_map(lambda _: self._get_status()), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._update_status, on_error=self._handle_refresh_error))
def requestQuotes(self, tickers): logger.debug(f'QuoteObserver.requestQuotes({tickers})') self.quoteSubscription = create( lambda o, s: beginStreamingQuotes(tickers, o, s)).pipe( op.subscribe_on(config.pool_scheduler), op.observe_on(config.pool_scheduler), op.do_action(lambda q: logger.debug(f'QO: {q}')), op.group_by(lambda q: q['symbol']), ).subscribe(on_next=self.handleQuote, on_error=lambda e: logger.debug(e), on_completed=lambda: logger.debug( 'QuoteObserver subscription completed'))
def test_input_port_updated_subject(self): def _subscribe(x=None): print(x) self.loop.stop() def _err(x=None): self.loop.stop() self.fail(x) self.instance.input_port_updated\ .pipe(operators.observe_on(self.executor))\ .subscribe(_subscribe, _err) self.loop.run_forever()
def enqueue(self, observable: Observable, group: str = 'default-group', retries: int = 0, description: str = None) -> Observable: def log_status(status): logging.debug( str({ 'WorkQueue': str(self), 'group': group, status: description })) log_status('ENQUEUED') output = Subject() errors = Subject() output_finalized = Subject() def handle_error(e, _): log_status('FAILED') errors.on_next(e) return empty() def set_output_finalized(): output_finalized.on_next(True) work = of(True).pipe( do_action(lambda _: log_status('STARTED')), take_until(output_finalized), flat_map(lambda _: observable.pipe( map(lambda value: of({ 'value': value, 'output': output })), retry_with_backoff( retries=retries, description='{}.enqueue(group={}, description={})'.format( self, group, description)), catch(handler=handle_error), take_until(output_finalized), take_until_disposed())), concat(of(of({ 'completed': True, 'output': output }))), finally_action(lambda: log_status('COMPLETED'))) self._queue.on_next({'work': work, 'group': group}) return output.pipe(observe_on(self.request_scheduler), throw_when(errors), take_while(lambda r: not r.get('completed')), map(lambda r: r.get('value')), finally_action(set_output_finalized))
def _simex_configure_subscription(self, x=None): self.subjects.image_producer.pipe( operators.observe_on(self.execution_thread), operators.map(lambda acquired_image: acquired_image.image ), # pluck the image array operators.map(lambda im: np.median(im)), operators.buffer_with_count(self.config["buffer_count"]), operators.map(lambda medians: np.mean(medians)), operators.take_until(self._stop) ).subscribe( ErrorToConsoleObserver(lambda t: self.instance.request_port_update( OutputPorts.BRIGHTNESS.value, np.asarray(t, dtype=np.float64)). subscribe(ErrorToConsoleObserver())))
def __init__(self, obs_stream, symbol): logger.debug(f'Stock.__init__({symbol})') self.obs_stream = obs_stream self.symbol = symbol self.price = () self.stockSubscription = self.obs_stream.pipe( op.subscribe_on(config.pool_scheduler), op.observe_on(config.pool_scheduler), op.do_action(lambda s: logger.debug(f'STK: {s}')), ).subscribe( on_next=self.handleQuote, on_error=lambda e: logger.debug(e), on_completed=lambda: logger.debug('Stock subscription completed'))
def _set_fan_speed(self, gpu_index: int, speed: int = 100, manual_control: bool = True) -> None: self._composite_disposable.add( self._set_fan_speed_interactor.execute( gpu_index, speed, manual_control).pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_error=lambda e: (LOG.exception(f"Set cooling error: {str(e)}"), self.main_view.set_statusbar_text( 'Error applying fan profile!'))))
def _set_speed_profile(self, profile: SpeedProfile) -> None: observable = self._set_speed_profile_interactor \ .execute(profile.channel, self._get_profile_data(profile)) self._composite_disposable.add( observable.pipe( operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe( on_next=lambda _: self._update_current_speed_profile(profile), on_error=lambda e: (_LOG.exception("Set cooling error: %s", str(e)), self.main_view.set_statusbar_text( 'Error applying %s speed profile!' % profile.channel))))
def test_observe_on_forward_subscribe_scheduler(self): scheduler = ImmediateScheduler() expected_subscribe_scheduler = ImmediateScheduler() actual_subscribe_scheduler = None def subscribe(observer, scheduler): nonlocal actual_subscribe_scheduler actual_subscribe_scheduler = scheduler observer.on_completed() xs = rx.create(subscribe) xs.pipe(ops.observe_on(scheduler)).subscribe( scheduler=expected_subscribe_scheduler) assert expected_subscribe_scheduler == actual_subscribe_scheduler
def create(): return xs.pipe(ops.observe_on(scheduler))