|
117 | 117 | "metadata": {}, |
118 | 118 | "outputs": [], |
119 | 119 | "source": [ |
120 | | - "def scatter_plot(x, y, size, color, scheme=branca.colormap.linear.RdBu_11, stroke_color='black', canvas=None):\n", |
121 | | - " canvas, drawarea, scale_x, scale_y, unscale_x, unscale_y, colormap = init_2d_plot(x, y, color, scheme, canvas=canvas)\n", |
122 | | - "\n", |
123 | | - " with hold_canvas(canvas):\n", |
124 | | - " canvas.clear()\n", |
125 | | - " canvas[1].save()\n", |
126 | | - "\n", |
127 | | - " draw_background(canvas[0], drawarea, unscale_x, unscale_y)\n", |
128 | | - "\n", |
129 | | - " # Draw scatter\n", |
130 | | - " n_marks = min(x.shape[0], y.shape[0], size.shape[0], color.shape[0])\n", |
131 | | - "\n", |
132 | | - " canvas[1].stroke_style = stroke_color\n", |
133 | | - "\n", |
134 | | - " for idx in range(n_marks):\n", |
135 | | - " canvas[1].fill_style = colormap(color[idx])\n", |
136 | | - " \n", |
137 | | - " mark_x = scale_x(x[idx])\n", |
138 | | - " mark_y = scale_y(y[idx])\n", |
139 | | - " mark_size = size[idx]\n", |
140 | | - "\n", |
141 | | - " canvas[1].fill_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n", |
142 | | - " canvas[1].stroke_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n", |
143 | | - "\n", |
144 | | - " canvas[1].restore()\n", |
145 | | - "\n", |
146 | | - " def click_handler(pixel_x, pixel_y):\n", |
147 | | - " unscaled_x = unscale_x(pixel_x)\n", |
148 | | - " unscaled_y = unscale_y(pixel_y)\n", |
149 | | - "\n", |
150 | | - " for idx in range(n_marks):\n", |
151 | | - " mark_x = x[idx]\n", |
152 | | - " mark_y = y[idx]\n", |
153 | | - " mark_size = size[idx]\n", |
154 | | - "\n", |
155 | | - " if (pixel_x > scale_x(mark_x) - mark_size and pixel_x < scale_x(mark_x) + mark_size and\n", |
156 | | - " pixel_y > scale_y(mark_y) - mark_size and pixel_y < scale_y(mark_y) + mark_size):\n", |
157 | | - " canvas[2].fill_style = 'red'\n", |
158 | | - " canvas[2].fill_arc(scale_x(mark_x), scale_y(mark_y), mark_size, 0, 2 * pi)\n", |
159 | | - "\n", |
160 | | - " canvas[2].on_click(click_handler)\n", |
161 | | - "\n", |
162 | | - " return canvas" |
| 120 | + "class Scatter_plot(object):\n", |
| 121 | + " def __init__(self, x, y, size, color, scheme=branca.colormap.linear.RdBu_11, stroke_color='black', canvas=None):\n", |
| 122 | + " \n", |
| 123 | + " self.dragging = False\n", |
| 124 | + " self.x = x\n", |
| 125 | + " self.y = y\n", |
| 126 | + " self.size = size\n", |
| 127 | + " self.color = color\n", |
| 128 | + " self.stroke_color = stroke_color\n", |
| 129 | + " self.canvas, self.drawarea, self.scale_x, self.scale_y, self.unscale_x, self.unscale_y, self.colormap = init_2d_plot(x, y, color, scheme, canvas=canvas)\n", |
| 130 | + " self.show()\n", |
| 131 | + " \n", |
| 132 | + " self.canvas[2].on_mouse_down(self.mouse_down_handler)\n", |
| 133 | + " self.canvas[2].on_mouse_move(self.mouse_move_handler)\n", |
| 134 | + " self.canvas[2].on_mouse_up(self.mouse_up_handler)\n", |
| 135 | + "\n", |
| 136 | + " def _ipython_display_(self):\n", |
| 137 | + " display(self.canvas)\n", |
| 138 | + "\n", |
| 139 | + " def show(self):\n", |
| 140 | + " with hold_canvas(self.canvas):\n", |
| 141 | + " self.canvas.clear()\n", |
| 142 | + " self.canvas[1].save()\n", |
| 143 | + "\n", |
| 144 | + " draw_background(self.canvas[0], self.drawarea, self.unscale_x, self.unscale_y)\n", |
| 145 | + "\n", |
| 146 | + " # Draw scatter\n", |
| 147 | + " self.n_marks = min(x.shape[0], y.shape[0], self.size.shape[0], self.color.shape[0])\n", |
| 148 | + "\n", |
| 149 | + " self.canvas[1].stroke_style = self.stroke_color\n", |
| 150 | + "\n", |
| 151 | + " for idx in range(self.n_marks):\n", |
| 152 | + " self.canvas[1].fill_style = self.colormap(self.color[idx])\n", |
| 153 | + "\n", |
| 154 | + " mark_x = self.scale_x(x[idx])\n", |
| 155 | + " mark_y = self.scale_y(y[idx])\n", |
| 156 | + " mark_size = self.size[idx]\n", |
| 157 | + "\n", |
| 158 | + " self.canvas[1].fill_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n", |
| 159 | + " self.canvas[1].stroke_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n", |
| 160 | + "\n", |
| 161 | + " self.canvas[1].restore()\n", |
| 162 | + "\n", |
| 163 | + " def mouse_down_handler(self, pixel_x, pixel_y):\n", |
| 164 | + " for idx in range(self.n_marks):\n", |
| 165 | + " mark_x = self.x[idx]\n", |
| 166 | + " mark_y = self.y[idx]\n", |
| 167 | + " mark_size = self.size[idx]\n", |
| 168 | + "\n", |
| 169 | + " if (pixel_x > self.scale_x(mark_x) - mark_size and pixel_x < self.scale_x(mark_x) + mark_size and\n", |
| 170 | + " pixel_y > self.scale_y(mark_y) - mark_size and pixel_y < self.scale_y(mark_y) + mark_size):\n", |
| 171 | + " self.i_mark = idx\n", |
| 172 | + " self.dragging = True\n", |
| 173 | + " break\n", |
| 174 | + " \n", |
| 175 | + " def mouse_move_handler(self, pixel_x, pixel_y):\n", |
| 176 | + " if self.dragging:\n", |
| 177 | + " unscaled_x = self.unscale_x(pixel_x)\n", |
| 178 | + " unscaled_y = self.unscale_y(pixel_y)\n", |
| 179 | + " self.x[self.i_mark] = unscaled_x\n", |
| 180 | + " self.y[self.i_mark] = unscaled_y\n", |
| 181 | + " self.show()\n", |
| 182 | + " \n", |
| 183 | + " def mouse_up_handler(self, pixel_x, pixel_y):\n", |
| 184 | + " self.dragging = False" |
163 | 185 | ] |
164 | 186 | }, |
165 | 187 | { |
|
264 | 286 | "cell_type": "markdown", |
265 | 287 | "metadata": {}, |
266 | 288 | "source": [ |
267 | | - "### Scatter marks are clickable! Try clicking on them" |
| 289 | + "### Scatter marks are draggable! Move the mouse while clicking on them..." |
268 | 290 | ] |
269 | 291 | }, |
270 | 292 | { |
|
278 | 300 | "sizes = np.random.randint(2, 8, n_points)\n", |
279 | 301 | "colors = np.random.rand(n_points) * 10 - 2\n", |
280 | 302 | "\n", |
281 | | - "plot = scatter_plot(x, y, sizes, colors, branca.colormap.linear.viridis, stroke_color='white')\n", |
| 303 | + "plot = Scatter_plot(x, y, sizes, colors, branca.colormap.linear.viridis, stroke_color='white')\n", |
282 | 304 | "plot" |
283 | 305 | ] |
284 | 306 | }, |
|
0 commit comments