예제 #1
0
    def __init__(self, client: MQTTClientWrapper, name="fp50", config=None):
        super().__init__(name, config=config)
        self.client = client

        self.topic_base = self.config["waterBath"][name]["topicBase"]
        self.topic = self.topic_base + "/setpoint"
        self.message_subject = Subject()

        self.client.subscribe(self.topic_base + "/power")
        self.client.subscribe(self.topic_base + "/temperature")
        self.client.subscribe(self.topic_base + "/setpoint")

        power_sub = Subject()
        temp_sub = Subject()
        setpoint_sub = Subject()
        self.client.message_callback_add(self.topic_base + "/power", lambda *args: power_sub.on_next(args))
        self.client.message_callback_add(self.topic_base + "/temperature", lambda *args: temp_sub.on_next(args))
        self.client.message_callback_add(self.topic_base + "/setpoint", lambda *args: setpoint_sub.on_next(args))
        rx.combine_latest(
            power_sub,
            temp_sub,
            setpoint_sub
        ).pipe(
            operators.map(lambda x: FP50Message(
                float(x[0][2].payload),
                float(x[1][2].payload),
                float(x[2][2].payload)
            ))
        ).subscribe(
            self.message_subject
        )
예제 #2
0
def main():
    # setup gui
    image = Image.open(IMAGE_FILE)
    image_width, image_height = image.size
    window_size = RectSize(width=image_width, height=image_height)
    window = initialize_window(window_size)
    canvas = create_canvas_on(window, window_size, canvas_place=Point(0, 0))
    image_tk = ImageTk.PhotoImage(image)
    canvas.create_image(0, 0, image=image_tk, anchor="nw")

    def draw_rect(rectangle):
        canvas.delete("rect")
        draw_rect_on(
            canvas,
            rectangle,
            fill_color="orange",
            stipple="gray12",
            outline_color="orange",
            width=1.0,
            tag="rect",
        )

    # state
    mouse_left_click = createMouseEventStream(window, "<Button-1>")
    mouse_left_drag = createMouseEventStream(window, "<B1-Motion>")
    rect_begin = mouse_left_click
    rect_end = rx.merge(mouse_left_drag, mouse_left_click)
    rect = rx.combine_latest(rect_begin, rect_end).pipe(
        ops.map(lambda tpl: rect_from_2points(*tpl)))

    rect.subscribe(draw_rect)

    window.mainloop()
예제 #3
0
def combine_latest(
    # *streams: rx.typing.Observable,
    s1: Optional[rx.typing.Observable[T1]] = None,
    s2: Optional[rx.typing.Observable[T2]] = None,
    s3: Optional[rx.typing.Observable[T3]] = None,
) -> Any:
    return rx.combine_latest(cast(rx.Observable, [s1, s2, s3]))
예제 #4
0
    def __init__(self, context: BlenderContext) -> None:
        super().__init__(context)

        self._position = Subject()
        self._activeInputs = Subject()

        # noinspection PyTypeChecker
        self.position = self._position.pipe(
            ops.distinct_until_changed(),
            ops.map(lambda v: tuple(
                p * s for p, s in zip(v, context.window_size.tuple))),
            ops.map(Point.from_tuple), ops.share())

        codes = {
            MouseButton.LEFT: bge.events.LEFTMOUSE,
            MouseButton.MIDDLE: bge.events.MIDDLEMOUSE,
            MouseButton.RIGHT: bge.events.RIGHTMOUSE
        }

        def pressed(e: SCA_InputEvent) -> bool:
            return KX_INPUT_ACTIVE in e.status or KX_INPUT_JUST_ACTIVATED in e.status

        def value_for(button: MouseButton) -> Observable:
            code = codes[button]

            return self._activeInputs.pipe(
                ops.start_with({}),
                ops.map(lambda i: code in i and pressed(i[code])),
                ops.map(lambda v: button if v else 0))

        # noinspection PyTypeChecker
        self.buttons = rx.combine_latest(
            *[value_for(b) for b in MouseButton]).pipe(
                ops.map(lambda v: reduce(lambda a, b: a | b, v)),
                ops.distinct_until_changed(), ops.share())
예제 #5
0
    def __init__(self, uri, config, masterGraph, mqtt, influx):
        self.uri = uri
        self.config = config
        self.masterGraph = masterGraph
        self.mqtt = mqtt
        self.influx = influx

        self.mqttTopic = self.topicFromConfig(self.config)

        statPath = '/subscribed_topic/' + self.mqttTopic.decode(
            'ascii').replace('/', '|')
        scales.init(self, statPath)
        self._mqttStats = scales.collection(statPath + '/incoming',
                                            scales.IntStat('count'),
                                            scales.RecentFpsStat('fps'))

        rawBytes = self.subscribeMqtt()
        rawBytes = rx.operators.do_action(self.countIncomingMessage)(rawBytes)
        parsed = self.getParser()(rawBytes)

        g = self.config
        for conv in g.items(g.value(self.uri, ROOM['conversions'])):
            parsed = self.conversionStep(conv)(parsed)

        outputQuadsSets = rx.combine_latest(*[
            self.makeQuads(parsed, plan)
            for plan in g.objects(self.uri, ROOM['graphStatements'])
        ])

        outputQuadsSets.subscribe_(self.updateQuads)
예제 #6
0
    def start(self, args: dict):
        from alleycat.ui.blender import UI

        self.context = UI().create_context()

        window = Frame(self.context, BorderLayout())
        window.bounds = Bounds(160, 70, 280, 200)

        panel = Panel(self.context, HBoxLayout())
        panel.set_color(StyleKeys.Background, RGBA(0.3, 0.3, 0.3, 0.8))

        window.add(panel, padding=Insets(10, 10, 10, 10))

        icon = Canvas(self.context, self.context.toolkit.images["cat.png"])
        icon.minimum_size_override = Some(Dimension(64, 64))

        panel.add(icon)

        label = Label(self.context, text_size=18)
        label.set_color(StyleKeys.Text, RGBA(1, 1, 1, 1))

        panel.add(label)

        button1 = LabelButton(self.context, text_size=16, text="Button 1")
        button2 = LabelButton(self.context, text_size=16, text="Button 2")

        buttons = Panel(self.context,
                        HBoxLayout(spacing=10, direction=BoxDirection.Reverse))

        buttons.add(button2)
        buttons.add(button1)

        window.add(buttons, Border.Bottom, Insets(0, 10, 10, 10))

        def handle_button(button: str):
            if len(button) > 0:
                label.text = f"{button} is pressed"
                panel.set_color(StyleKeys.Background, RGBA(1, 0, 0, 1))
            else:
                label.text = ""
                panel.set_color(StyleKeys.Background, RGBA(0.1, 0.1, 0.1, 0.8))

        button1_active = button1.observe("active").pipe(
            ops.map(lambda v: "Button 1" if v else ""))
        button2_active = button2.observe("active").pipe(
            ops.map(lambda v: "Button 2" if v else ""))

        button_active = rx.combine_latest(button1_active, button2_active).pipe(
            ops.map(lambda v: v[0] + v[1]))

        button_active.subscribe(handle_button,
                                on_error=self.context.error_handler)

        window.draggable = True
        window.resizable = True
예제 #7
0
    def __init__(self, client: MQTTClientWrapper, name="fp50", config=None):
        super().__init__(name, config=config)
        self.client = client

        self.topic_base = self.config["waterBath"][name]["topicBase"]
        self.topic = self.topic_base + "/setpoint"
        self.message_subject = Subject()

        self.client.subscribe(self.topic_base + "/crystallizer_temperature")
        self.client.subscribe(self.topic_base + "/setpoint")
        self.interval_scheduler = NewThreadScheduler()

        def update(x, scheduler=None):
            self.client.publish(self.topic_base + "/crystallizer_temperature",
                                None)

        rx.interval(self.config["waterBath"][name]["interval"],
                    self.interval_scheduler).subscribe(update)

        def convert(x):
            payloads = [xx[2].payload for xx in x]
            for p in payloads:
                if not p:
                    # skipping conversion request
                    return None

            return {
                # "power": float(payloads[0]),
                # "internal_temperature": float(payloads[1]),
                "crystallizer_temperature": float(payloads[0]),
                "setpoint": float(payloads[1]),
            }

        rx.combine_latest(
            from_callback(
                self.client.message_callback_add)(self.topic_base +
                                                  "/crystallizer_temperature"),
            from_callback(self.client.message_callback_add)(self.topic_base +
                                                            "/setpoint"),
        ).pipe(operators.map(convert),
               operators.filter(lambda x: x is not None),
               operators.debounce(0.6)).subscribe(self.message_subject)
예제 #8
0
def main():
    dbus = DBus.new_tcp_connection('192.168.178.137')
    service_name = 'com.victronenergy.example'

    def always(_):
        return True

    dbus.publish_ve_property(service_name, '/ProductName', 'Example Product')
    dbus.publish_ve_property(service_name, '/YouCannotEditMe', 'try it')
    dbus.publish_ve_property(service_name,
                             '/EnterNumberBetween0and10',
                             5,
                             accept_change=lambda n: 0 <= float(n) <= 10)
    dbus.publish_ve_property(service_name,
                             '/EnterSalutation',
                             'Hello',
                             accept_change=always)
    dbus.publish_ve_property(service_name,
                             '/EnterYourName',
                             '',
                             accept_change=always)
    dbus.publish_ve_property(service_name, '/Greetings',
                             'please enter a name and a salutation')

    def update_counter(i):
        dbus.publish_ve_property(service_name, '/Counter', i)

    rx.interval(timedelta(seconds=1)).subscribe(update_counter)

    def greeter(s_n: Tuple[VeProperty, VeProperty]):
        s, n = s_n
        salutation = s.text
        name = n.text

        greeting = f'{salutation} {name}' if salutation and name else 'please enter a name and a salutation'
        dbus.publish_ve_property(service_name, '/Greetings', greeting)

    salutation = dbus.observe_ve_property(service_name, '/EnterSalutation')
    name = dbus.observe_ve_property(service_name, '/EnterYourName')
    rx.combine_latest(salutation, name).subscribe(greeter)

    dbus.run_forever()
예제 #9
0
    def combine_latest(source: Observable) -> Observable:
        """Merges the specified observable sequences into one
        observable sequence by creating a tuple whenever any
        of the observable sequences produces an element.

        Examples:
            >>> obs = combine_latest(source)

        Returns:
            An observable sequence containing the result of combining
            elements of the sources into a tuple.
        """

        sources = (source,) + others

        return rx.combine_latest(*sources)
예제 #10
0
    def combine_latest(source: Observable) -> Observable:
        """Merges the specified observable sequences into one
        observable sequence by creating a tuple whenever any
        of the observable sequences produces an element.

        Examples:
            >>> obs = combine_latest(source)

        Returns:
            An observable sequence containing the result of combining
            elements of the sources into a tuple.
        """

        sources = (source, ) + others

        return rx.combine_latest(*sources)
예제 #11
0
 def _export_geometry(geometry, geometry_description):
     export_years = combine_latest(
         *[_export_year(
             geometry=geometry,
             year_start=year_range[0],
             year_end=year_range[1],
             export_description='{}_{}_{}'.format(geometry_description, year_range[0].year, description),
             year_dir='/'.join([download_dir, description, geometry_description, str(year_range[0].year)])
         ) for year_range in year_ranges]
     ).pipe(
         map(lambda progresses: _sum_dicts(progresses)),
         map(lambda p: {**p, 'geometry': geometry_description})
     )
     process_geometry = _process_geometry('/'.join([download_dir, description, geometry_description]))
     return concat(
         export_years,
         process_geometry
     )
예제 #12
0
    def combine_latest(source: Observable) -> Observable:
        """Merges the specified observable sequences into one
        observable sequence by creating a tuple whenever any
        of the observable sequences produces an element.

        Examples:
            >>> obs = combine_latest(source)

        Returns:
            An observable sequence containing the result of combining
            elements of the sources into a tuple.
        """
        sources: List[Observable] = [source]

        if isinstance(other, typing.Observable):
            sources += [other]
        else:
            sources += other

        return rx.combine_latest(sources)
예제 #13
0
파일: download.py 프로젝트: mlateb/sepal
    def download_folder(folder):
        def aggregate_progress(progresses: list):
            total_files = len(progresses)
            total_bytes = sum([int(p['file']['size']) for p in progresses])
            downloaded_files = len([
                p for p in progresses
                if p['downloaded_bytes'] == p['total_bytes']
            ])
            downloaded_bytes = sum([p['downloaded_bytes'] for p in progresses])

            return {
                'downloaded_files': downloaded_files,
                'downloaded_bytes': downloaded_bytes,
                'total_files': total_files,
                'total_bytes': total_bytes
            }

        return list_folder_recursively(credentials, folder).pipe(
            map(lambda files: filter_files(files)),
            flat_map(lambda files: combine_latest(
                *[download_file(f, get_file_destination(f)) for f in files])),
            map(aggregate_progress))
예제 #14
0
    def download_folder(folder):
        def aggregate_progress(progresses: list):
            total_files = len(progresses)
            total_bytes = sum([int(p.file['size']) for p in progresses])
            downloaded_files = len(
                [p for p in progresses if p.downloaded_bytes == p.total_bytes])
            downloaded_bytes = sum([p.downloaded_bytes for p in progresses])

            return progress(
                default_message=
                'Downloaded {downloaded_files} of {total_files} files ({downloaded} of {total})',
                message_key='tasks.drive.download_folder',
                downloaded_files=downloaded_files,
                downloaded_bytes=downloaded_bytes,
                downloaded=format_bytes(downloaded_bytes),
                total_files=total_files,
                total_bytes=total_bytes,
                total=format_bytes(total_bytes))

        return list_folder_recursively(credentials, folder).pipe(
            map(lambda files: filter_files(files)),
            flat_map(lambda files: combine_latest(
                *[download_file(f, get_file_destination(f)) for f in files])
                     if files else empty()), flat_map(aggregate_progress))
def audio_encoder(sources):
    # Parse configuration
    parser = create_arg_parser()

    parsed_argv = sources.argv.argv.pipe(
        ops.skip(1),
        argparse.parse(parser),
        ops.filter(lambda i: i.key == 'config'),
        ops.subscribe_on(aio_scheduler),
        ops.share(),
    )

    # monitor and parse config file
    monitor_init = parsed_argv.pipe(
        ops.flat_map(lambda i: rx.from_([
            inotify.AddWatch(
                id='config', path=i.value, flags=aionotify.Flags.MODIFY),
            inotify.Start(),
        ])))

    config_update = sources.inotify.response.pipe(
        ops.debounce(5.0, scheduler=aio_scheduler),
        ops.map(lambda i: True),
        ops.start_with(True),
    )

    read_request, read_response = rx.combine_latest(
        parsed_argv, config_update).pipe(
            ops.starmap(
                lambda config, _: file.Read(id='config', path=config.value)),
            file.read(sources.file.response),
        )

    config = read_response.pipe(
        ops.filter(lambda i: i.id == "config"),
        ops.flat_map(lambda i: i.data),
        parse_config,
    )

    # Transcode request handling
    encode_init = config.pipe(
        ops.map(lambda i: i.encode),
        ops.distinct_until_changed(),
        ops.map(lambda i: encoder.Configure(samplerate=i.samplerate,
                                            bitdepth=i.bitdepth)),
    )

    encode_request = sources.httpd.route.pipe(
        ops.filter(lambda i: i.id == 'flac_transcode'),
        ops.flat_map(lambda i: i.request),
        ops.flat_map(lambda i: rx.just(i, encode_scheduler)),
        ops.map(lambda i: encoder.EncodeMp3(
            id=i.context, data=i.data, key=i.match_info['key'])),
    )
    encoder_request = rx.merge(encode_init, encode_request)

    # store encoded file
    store_requests = sources.encoder.response.pipe(
        ops.observe_on(s3_scheduler),
        ops.map(lambda i: s3.UploadObject(
            key=i.key + '.flac',
            data=i.data,
            id=i.id,
        )),
    )

    # acknowledge http request
    http_response = sources.s3.response.pipe(
        ops.map(lambda i: httpd.Response(
            data='ok'.encode('utf-8'),
            context=i.id,
        )))

    # http server
    http_init = config.pipe(
        ops.take(1),
        ops.flat_map(lambda i: rx.from_([
            httpd.Initialize(request_max_size=0),
            httpd.AddRoute(
                methods=['POST'],
                path='/api/transcode/v1/flac/{key:[a-zA-Z0-9-\._]*}',
                id='flac_transcode',
            ),
            httpd.StartServer(host=i.server.http.host, port=i.server.http.port
                              ),
        ])),
    )
    http = rx.merge(http_init, http_response)

    # s3 database
    s3_init = config.pipe(
        ops.take(1),
        ops.map(lambda i: s3.Configure(
            access_key=i.s3.access_key,
            secret_key=i.s3.secret_key,
            bucket=i.s3.bucket,
            endpoint_url=i.s3.endpoint_url,
            region_name=i.s3.region_name,
        )),
    )

    # merge sink requests
    file_requests = read_request
    s3_requests = rx.merge(s3_init, store_requests)

    return Sink(
        encoder=encoder.Sink(request=encoder_request),
        s3=s3.Sink(request=s3_requests),
        file=file.Sink(request=file_requests),
        httpd=httpd.Sink(control=http),
        inotify=inotify.Sink(request=monitor_init),
    )
예제 #16
0
 def _repeat_when_player_comes_online(self, obs):
     return rx.combine_latest(
         self.obs_teams, self._obs_player_came_online).pipe(
             ops.map(lambda t: t[0])
         )
def main(sources):
    example1_completed = rx.combine_latest(
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example1_set_head_angle")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example1_set_lift_height")),
    )
    example2_completed = rx.combine_latest(
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example2_drive_straight")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example2_turn_in_place")),
    )
    example3_completed = rx.combine_latest(
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example3_set_lift_height")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example3_set_head_angle")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example3_drive_straight")),
        sources["Cozmo"].pipe(
            ops.filter(
                lambda i: i["id"] is "example3_display_oled_face_image")),
    )
    example4_completed = rx.combine_latest(
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example4_set_lift_height")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example4_set_head_angle")),
        sources["Cozmo"].pipe(
            ops.filter(lambda i: i["id"] is "example4_drive_straight")),
        sources["Cozmo"].pipe(
            ops.filter(
                lambda i: i["id"] is "example4_display_oled_face_image")),
    )
    example1_completed.subscribe(on_next=lambda i: print("example1_completed"))
    example2_completed.subscribe(on_next=lambda i: print("example2_completed"))
    example3_completed.subscribe(on_next=lambda i: print("example3_completed"))
    example4_completed.subscribe(on_next=lambda i: print("example4_completed"))
    rxcozmo = rx.merge(
        # example1_lift_head
        rx.of({
            "id": "example1_set_head_angle",
            "name": "set_head_angle",
            "value": cozmo.robot.MAX_HEAD_ANGLE,
        }),
        rx.of({
            "id": "example1_set_lift_height",
            "name": "set_lift_height",
            "value": 1.0,
        }),
        # example2_conflicting_actions
        example1_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example2_drive_straight",
                    "name": "drive_straight",
                    "value": {
                        "distance": distance_mm(50),
                        "speed": speed_mmps(25),
                        "should_play_anim": False,
                    },
                })),
        example1_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example2_turn_in_place",
                    "name": "turn_in_place",
                    "value": {
                        "angle": degrees(90),
                    },
                })),
        # example3_abort_one_action
        example2_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example3_set_lift_height",
                    "name": "set_lift_height",
                    "value": 0,
                })),
        example2_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example3_set_head_angle",
                    "name": "set_head_angle",
                    "value": {
                        "angle": cozmo.robot.MIN_HEAD_ANGLE,
                        "duration": 6.0,
                    },
                })),
        example2_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example3_drive_straight",
                    "name": "drive_straight",
                    "value": {
                        "distance": distance_mm(75),
                        "speed": speed_mmps(25),
                        "should_play_anim": False,
                    },
                })),
        example2_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example3_display_oled_face_image",
                    "name": "display_oled_face_image",
                    "value": {
                        "screen_data": face_image,
                        "duration_ms": 30000.0,
                    },
                })),
        # abort actions
        example2_completed.pipe(
            ops.map(lambda i: {
                "type": "abort",
                "name": "set_lift_height"
            })),
        example2_completed.pipe(
            ops.delay(0.1),
            ops.map(lambda i: {
                "type": "abort",
                "name": "set_head_angle"
            }),
        ),
        example2_completed.pipe(
            ops.delay(2),
            ops.map(lambda i: {
                "type": "abort",
                "name": "display_oled_face_image"
            }),
        ),
        # example4_abort_all_actions
        example3_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example4_set_lift_height",
                    "name": "set_lift_height",
                    "value": 0.0,
                })),
        example3_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example4_set_head_angle",
                    "name": "set_head_angle",
                    "value": {
                        "angle": cozmo.robot.MIN_HEAD_ANGLE,
                        "duration": 6.0,
                    },
                })),
        example3_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example4_drive_straight",
                    "name": "drive_straight",
                    "value": {
                        "distance": distance_mm(75),
                        "speed": speed_mmps(25),
                        "should_play_anim": False,
                    },
                })),
        example3_completed.pipe(
            ops.map(
                lambda i: {
                    "id": "example4_display_oled_face_image",
                    "name": "display_oled_face_image",
                    "value": {
                        "screen_data": face_image,
                        "duration_ms": 30000.0,
                    },
                })),
        # abort all actions
        example3_completed.pipe(
            ops.delay(2),
            ops.map(lambda i: {
                "type": "abort",
                "name": "set_lift_height"
            }),
        ),
        example3_completed.pipe(
            ops.delay(2),
            ops.map(lambda i: {
                "type": "abort",
                "name": "set_head_angle"
            }),
        ),
        example3_completed.pipe(
            ops.delay(2),
            ops.map(lambda i: {
                "type": "abort",
                "name": "drive_straight"
            }),
        ),
        example3_completed.pipe(
            ops.delay(2),
            ops.map(lambda i: {
                "type": "abort",
                "name": "display_oled_face_image"
            }),
        ),
    )
    sinks = {"Cozmo": rxcozmo}
    return sinks
예제 #18
0
import rx
from rx.operators import map, start_with
from .streams import *


myTradeStream = rx.combine_latest(
    rx.interval(0.01).pipe(
    map(lambda _: datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
),
    PriceLastBuyStream.pipe(map(lambda res: 'last buy: ' + str(res)), start_with('waiting...')),
    PriceLastSellStream.pipe(map(lambda res: 'last sell: ' + str(res)), start_with('waiting...')),
    PriceMinAskStream.pipe(map(lambda res: 'min ask: ' + str(res)), start_with('waiting...')),
    PriceMaxBidStream.pipe(map(lambda res: 'max bid: ' + str(res)), start_with('waiting...')),
)
예제 #19
0
# flat 하면 리스트를 푼다.
# [[1,2], [3]] -> [1,2,3]
# 그리고 나서 map 한다. x -> x
# [1, 2, 3] -> [1, 2, 3]

print('-- window_with_time')

test_scheduler = TestScheduler()
rx.interval(0.05, test_scheduler).pipe(ops.take_until(
    rx.timer(0.1)), ops.window_with_time(0.01)).subscribe(
        lambda observable: observable.pipe(ops.count()).subscribe(print_value))
test_scheduler.start()
time.sleep(0.5)
# 결과가 이게 맞나?? 단위가 뭐지?

print('-- combine_latest')
rx.combine_latest(
    rx.interval(0.1).pipe(ops.map(lambda x: 'a- {}'.format(x))),
    rx.interval(0.2).pipe(ops.map(lambda x: 'b- {}'.format(x)))).pipe(
        ops.take_until(rx.timer(0.5))).subscribe(print_value)
time.sleep(1)
# 누가 먼저 결과를 배출할지 예상 불가

print('-- zip')
rx.zip(
    rx.interval(0.1).pipe(ops.map(lambda x: 'a- {}'.format(x))),
    rx.interval(0.2).pipe(ops.map(lambda x: 'b- {}'.format(x)))).pipe(
        ops.take_until(rx.timer(1))).subscribe(print_value)
time.sleep(1.2)
# zip 은 양쪽 모두 값이 있어야 된다
예제 #20
0
    ops.map(lambda res: res.bids),
    ops.filter(bool),
    ops.map(lambda ds: sorted(ds, key=lambda x: float(x[0]))),
    ops.map(lambda ds: float(ds[-1][0])),)


def buy(price, amount=AMOUNT):
    return bitbank.order(price, amount, 'buy', 'limit')


def sell(price, amount=AMOUNT):
    return bitbank.order(price, amount, 'sell', 'limit')


priceBuyMainStream = rx.combine_latest(
    PriceLastSellStream, PriceMaxBidStream).pipe(
    ops.map(lambda ps: (float(ps[0]) + float(ps[1])) / 2))

priceBuyLCStream = priceBuyMainStream.pipe(
    ops.map(lambda p: p + ALPHA))

priceSellMainStream = rx.combine_latest(
    PriceLastBuyStream, PriceMinAskStream).pipe(
    ops.map(lambda ps: (float(ps[0]) + float(ps[1])) / 2))

priceSellLCStream = priceSellMainStream.pipe(
    ops.map(lambda p: p - ALPHA))

initialOrderStream = canOrderStream.pipe(
    ops.filter(bool))
예제 #21
0
class Component(Drawable, StyleResolver, MouseEventHandler, EventDispatcher,
                ContextAware, ReactiveObject):
    visible: RP[bool] = rv.new_property()

    parent: RP[Maybe[Container]] = rv.from_value(Nothing)

    offset: RV[Point] = parent.as_view().map(lambda _, parent: parent.map(
        lambda p: rx.combine_latest(p.observe("offset"), p.observe("location"))
        .pipe(ops.map(lambda v: v[0] + v[1]))).or_else_call(lambda: rx.of(
            Point(0, 0)))).pipe(lambda _: (ops.exclusive(), ))

    _minimum_size: RP[Dimension] = rv.from_value(Dimension(0, 0))

    _preferred_size: RP[Dimension] = rv.from_value(Dimension(0, 0))

    minimum_size_override: RP[Maybe[Dimension]] = rv.from_value(Nothing)

    minimum_size: RV[Dimension] = rv.combine_latest(
        _minimum_size,
        minimum_size_override)(ops.pipe(ops.map(lambda v: v[1].value_or(v[0])),
                                        ops.distinct_until_changed()))

    preferred_size_override: RP[Maybe[Dimension]] = rv.from_value(
        Nothing).pipe(lambda o:
                      (ops.combine_latest(o.observe("minimum_size")),
                       ops.map(lambda t: t[0].map(lambda v: t[1].copy(
                           width=max(v.width, t[1].width),
                           height=max(v.height, t[1].height)))),
                       ops.distinct_until_changed()))

    preferred_size: RV[Dimension] = rv.combine_latest(
        _preferred_size, preferred_size_override, minimum_size)(ops.pipe(
            ops.map(lambda v: (v[1].value_or(v[0]), v[2])),
            ops.map(lambda v: v[0].copy(width=max(v[0].width, v[1].width),
                                        height=max(v[0].height, v[1].height))),
            ops.distinct_until_changed()))

    bounds: RP[Bounds] = Bounded.bounds.pipe(lambda o: (
        ops.combine_latest(o.observe("minimum_size")),
        ops.map(lambda v: v[0].copy(width=max(v[0].width, v[1].width),
                                    height=max(v[0].height, v[1].height))),
        ops.start_with(o.preferred_size)))

    def __init__(self, context: Context, visible: bool = True) -> None:
        if context is None:
            raise ValueError("Argument 'context' is required.")

        # noinspection PyTypeChecker
        self.visible = visible

        self._context = context
        self._valid = False
        self._ui = self.create_ui()

        assert self._ui is not None

        super().__init__()

        self.validate()

        self.ui \
            .on_invalidate(self) \
            .pipe(ops.take_until(self.on_dispose)) \
            .subscribe(lambda _: self.invalidate(), on_error=self.error_handler)

    @property
    def context(self) -> Context:
        return self._context

    @property
    def ui(self) -> ComponentUI:
        return self._ui

    @property
    def look_and_feel(self) -> LookAndFeel:
        return self.context.look_and_feel

    def create_ui(self) -> ComponentUI:
        return self.context.look_and_feel.create_ui(self)

    def show(self) -> None:
        # noinspection PyTypeChecker
        self.visible = True

    def hide(self) -> None:
        # noinspection PyTypeChecker
        self.visible = False

    @property
    def valid(self) -> bool:
        return self._valid

    # noinspection PyTypeChecker
    def validate(self, force: bool = False) -> None:
        if self.visible and (not self.valid or force):
            self._minimum_size = self.ui.minimum_size(self)
            self._preferred_size = self.ui.preferred_size(self)

            self._valid = True

            self.parent.map(lambda p: p.request_layout())

    def invalidate(self) -> None:
        self._valid = False

        self.parent.map(lambda p: p.invalidate())

    def draw(self, g: Graphics) -> None:
        if self.visible:
            g.save()

            (dx,
             dy) = self.parent.map(lambda p: p.location).value_or(Point(0, 0))
            (cx, cy, cw, ch) = self.ui.clip_bounds(self).tuple

            g.translate(dx, dy)
            g.rectangle(cx, cy, cw, ch)

            g.clip()

            try:
                self.draw_component(g)
            except BaseException as e:
                self.error_handler(e)

            g.restore()

    def draw_component(self, g: Graphics) -> None:
        self.ui.draw(g, self)

    def position_of(self, event: PositionalEvent) -> Point:
        if event is None:
            raise ValueError("Argument 'event' is required.")

        return event.position - self.offset

    @property
    def inputs(self) -> Mapping[str, Input]:
        return self.context.inputs

    @property
    def parent_dispatcher(self) -> Maybe[EventDispatcher]:
        # noinspection PyTypeChecker
        return self.parent

    def __repr__(self) -> Any:
        return str({"id": id(self), "type": type(self).__name__})
예제 #22
0
def chronometer(valid=None,
                offset=None,
                start=None,
                source=None,
                radio_group=None,
                plus_button=None,
                minus_button=None,
                selectors=None):
    """
    Time/forecast exploration widget

    Creates a figure with glyphs for each point in
    time/forecast space along with +/- buttons and a
    radio group to navigate subsets of available
    forecasts

    >>> source = bokeh.models.ColumnDataSource({
    ...     "valid": [],
    ...     "start": [],
    ...     "offset": []
    ... })
    >>> figure, radio_group, plus, minus = chronometer(
    ...     valid="valid",
    ...     start="start",
    ...     offset="offset",
    ...     source=source)
    >>> isinstance(figure, bokeh.plotting.Figure)
    True

    The associated glyphs react to changes in
    the `source.selected.indices` and clicks from the
    radio group, plus and minus buttons

    >>> import datetime as dt
    >>> source.stream({
    ...     "valid": [dt.datetime(2018, 1, 1, 12)],
    ...     "start": [dt.datetime(2018, 1, 1, 0)],
    ...     "offset": [12]
    ... })
    >>> source.selected.indices = [0]

    **Selectors**

    The radio group allows the user to choose between
    time/forecast selection algorithms, the user
    is also able to specify their own time/forecast
    space selection algorithm

    >>> selectors = {
    ...     0: select("key"),
    ... }

    The keys of the selectors dict maps radio
    group active index to functions that select
    points in the column data source

    **Widgets**

    A figure, a radio group and buttons for navigating
    backwards/forwards inside a selection are returned
    to allow the user to craft their own layout

    :param valid: key in source
    :param start: key in source
    :param offset: key in source
    :param source: ColumnDataSource

    :returns: figure, radio group, plus button and
              minus button bokeh widgets
    """
    msg = ("please specify 'valid', 'start' and 'offset' " "keywords")
    assert valid is not None, msg
    assert start is not None, msg
    assert offset is not None, msg
    if radio_group is None:
        radio_group = bokeh.models.RadioGroup(
            labels=["Time", "Forecast", "Run"],
            inline=True,
            width=210,
            active=2)
    if selectors is None:
        selectors = {
            0: select(valid),
            1: select(offset),
            2: select(start),
        }
    if plus_button is None:
        plus_button = bokeh.models.Button(label="+", width=50)
    if minus_button is None:
        minus_button = bokeh.models.Button(label="-", width=50)
    hover_tool = bokeh.models.HoverTool(tooltips=[
        ('valid', '@' + valid + '{%F %T}'), ('start', '@' + start + '{%F %T}'),
        ('length', 'T+@' + offset)
    ],
                                        formatters={
                                            valid: 'datetime',
                                            start: 'datetime'
                                        })
    pan_tool = bokeh.models.PanTool(dimensions="width")
    tap_tool = bokeh.models.TapTool()
    figure = bokeh.plotting.figure(
        x_axis_type='datetime',
        plot_height=200,
        plot_width=350,
        tools=[tap_tool, hover_tool, pan_tool, "xwheel_zoom"],
        active_scroll="xwheel_zoom",
        toolbar_location=None)
    figure.toolbar.active_inspect = hover_tool
    figure.ygrid.grid_line_color = None
    figure.xaxis.axis_label = "Validity time"
    figure.xaxis.axis_label_text_font_size = "10px"
    figure.yaxis.axis_label = "Forecast length"
    figure.yaxis.axis_label_text_font_size = "10px"
    offsets = source.data[offset][:]
    if len(offsets) > 0:
        figure.yaxis.ticker = ticks(max(offsets))
    renderer = figure.square(x=valid,
                             y=offset,
                             source=source,
                             size=8,
                             line_color=None,
                             nonselection_alpha=1,
                             nonselection_line_color=None)
    tap_tool.renderers = [renderer]

    second_source = bokeh.models.ColumnDataSource({
        valid: [],
        offset: [],
        start: []
    })
    renderer = figure.square(x=valid, y=offset, size=8, source=second_source)
    renderer.selection_glyph = bokeh.models.Square(fill_alpha=1,
                                                   fill_color="Red",
                                                   line_color="Black")
    renderer.nonselection_glyph = bokeh.models.Square(fill_alpha=1,
                                                      fill_color="White",
                                                      line_color="Black")

    selected = rx.Stream()
    source.selected.on_change('indices', rx.callback(selected))

    active = rx.Stream()
    radio_group.on_change("active", rx.callback(active))
    changes = rx.combine_latest(active.map(lambda i: selectors[i]),
                                selected).filter(all_not_none)

    def render(source, second_source):
        """Updates secondary source used to highlight selection"""
        def wrapper(event):
            selector, indices = event
            if len(indices) == 0:
                indices = []
                data = {k: [] for k in source.data.keys()}
            else:
                index = indices[0]
                pts = selector(source, index)
                indices = [pts[0].tolist().index(index)]
                data = {k: np.asarray(v)[pts] for k, v in source.data.items()}
            second_source.data = data
            second_source.selected.indices = indices

        return wrapper

    changes.map(render(source, second_source))

    plus = rx.Stream()
    plus_button.on_click(rx.click(plus))
    plus = plus.map(+1)

    minus = rx.Stream()
    minus_button.on_click(rx.click(minus))
    minus = minus.map(-1)

    steps = rx.Merge(plus, minus)
    steps.map(move(second_source)).map(
        sync(source, second_source, valid=valid, offset=offset))

    if radio_group.active is not None:
        active.emit(radio_group.active)
    return figure, radio_group, plus_button, minus_button