Beispiel #1
0
    def setUp(self):
        self.path1 = Path([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3), (-0.2, 0.4),
                           (-0.3, 0.4)])

        self.path2 = Path([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3), (-0.2, 0.4),
                           (-3, 4)])

        self.contours1 = Contours([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3),
                                   (-0.2, 0.4), (-0.3, 0.4)],
                                  level=1)

        self.contours2 = Contours([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3),
                                   (-0.2, 0.4), (-3, 4)],
                                  level=1)

        self.contours3 = Contours([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3),
                                   (-0.2, 0.4), (-0.3, 0.4)],
                                  level=2)

        self.bounds1 = Bounds(0.3)
        self.bounds2 = Bounds(0.4)

        self.box1 = Box(-0.25, 0.3, 0.3)
        self.box2 = Box(-0.25, 0.3, 0.4)

        self.ellipse1 = Ellipse(-0.25, 0.3, 0.3)
        self.ellipse2 = Ellipse(-0.25, 0.3, 0.4)
Beispiel #2
0
    def setUp(self):
        self.path1 = Path([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3), (-0.2, 0.4),
                           (-0.3, 0.4)])

        self.path2 = Path([(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3), (-0.2, 0.4),
                           (-3, 4)])

        self.contours1 = Contours([(-0.3, 0.4, 1), (-0.3, 0.3, 1),
                                   (-0.2, 0.3, 1), (-0.2, 0.4, 1),
                                   (-0.3, 0.4, 1)],
                                  vdims='Level')

        self.contours2 = Contours([(-0.3, 0.4, 1), (-0.3, 0.3, 1),
                                   (-0.2, 0.3, 1), (-0.2, 0.4, 1), (-3, 4, 1)],
                                  vdims='Level')

        self.contours3 = Contours([(-0.3, 0.4, 2), (-0.3, 0.3, 2),
                                   (-0.2, 0.3, 2), (-0.2, 0.4, 2),
                                   (-0.3, 0.4, 2)],
                                  vdims='Level')

        self.bounds1 = Bounds(0.3)
        self.bounds2 = Bounds(0.4)

        self.box1 = Box(-0.25, 0.3, 0.3)
        self.box2 = Box(-0.25, 0.3, 0.4)

        self.ellipse1 = Ellipse(-0.25, 0.3, 0.3)
        self.ellipse2 = Ellipse(-0.25, 0.3, 0.4)
    def test_boundsxy_dynamic_map(self):
        # Build Holoviews Elements
        scatter = Scatter([0, 0])
        boundsxy = BoundsXY(source=scatter)
        dmap = DynamicMap(lambda bounds: Bounds(bounds)
                          if bounds is not None else Bounds((0, 0, 0, 0)),
                          streams=[boundsxy])

        # Convert to Dash
        components = to_dash(self.app, [scatter, dmap], reset_button=True)

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 2)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 1)

        # Get arguments passed to @app.callback decorator
        decorator_args = list(self.app.callback.call_args_list[0])[0]
        outputs, inputs, states = decorator_args

        # Check outputs
        expected_outputs = [(g.id, "figure") for g in components.graphs] + \
                           [(components.store.id, "data")]
        self.assertEqual([(output.component_id, output.component_property)
                          for output in outputs], expected_outputs)

        # Check inputs
        expected_inputs = [(g.id, prop) for g in components.graphs
                           for prop in ["selectedData", "relayoutData"]
                           ] + [(components.resets[0].id, "n_clicks")]

        self.assertEqual(
            [(ip.component_id, ip.component_property) for ip in inputs],
            expected_inputs,
        )

        # Check State
        expected_state = [(components.store.id, "data")]
        self.assertEqual(
            [(state.component_id, state.component_property)
             for state in states],
            expected_state,
        )

        # Check initial figures
        fig1 = components.graphs[0].figure
        fig2 = components.graphs[1].figure
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds the bounds element
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(fig2["layout"]["shapes"][0]["path"],
                         "M0 0L0 0L0 0L0 0L0 0Z")

        # Get callback function
        callback_fn = self.app.callback.return_value.call_args[0][0]

        # # mimic initial callback invocation
        store_value = encode_store_data(
            {"streams": {
                id(boundsxy): boundsxy.contents
            }})

        # Update store, then mimic a box selection on scatter figure
        # store_value = new_store
        with patch.object(
                CallbackContext, "triggered",
            [{
                "prop_id": inputs[0].component_id + ".selectedData"
            }]):
            [fig1, fig2,
             new_store] = callback_fn({"range": {
                 "x": [1, 2],
                 "y": [3, 4]
             }}, {}, {}, {}, 0, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds the bounds element
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(
            fig2["layout"]["shapes"][0]["path"],
            "M1 3L1 4L2 4L2 3L1 3Z",
        )

        # Check that store was updated
        self.assertEqual(decode_store_data(new_store), {
            "streams": {
                id(boundsxy): {
                    "bounds": (1, 3, 2, 4)
                }
            },
            "kdims": {}
        })

        # Click reset button
        with patch.object(CallbackContext, "triggered",
                          [{
                              "prop_id": components.resets[0].id + ".n_clicks"
                          }]):
            [fig1, fig2,
             new_store] = callback_fn({"range": {
                 "x": [1, 2],
                 "y": [3, 4]
             }}, {}, {}, {}, 1, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds reset bounds elemnt
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(fig2["layout"]["shapes"][0]["path"],
                         "M0 0L0 0L0 0L0 0L0 0Z")

        # Reset button should clear bounds in store
        self.assertEqual(
            decode_store_data(new_store), {
                "streams": {
                    id(boundsxy): {
                        "bounds": None
                    }
                },
                "reset_nclicks": 1,
                "kdims": {}
            })