<jupyter_start><jupyter_text>Color WheelFor this example we'll be making a simple color picker that's powered by python.<jupyter_code>import math
import purly<jupyter_output><empty_output><jupyter_text>To set things up we'll need to stand up our model server. By default the server has a max refresh rate of `25` hertz. However for this example to be convincingly smooth we'll want to bump that up to about `60`. If you want to unlock the refresh rate set `refresh=None`. We'll then hook up a layout object to a model resource (see the introductory example  or [read the docs](https://github.com/rmorshea/purlypurly) if this doesn't make sense).<jupyter_code>from example_utils import localhost

# increase model server refresh cap to 60 hertz.
purly.state.Machine(refresh=60).run()

# name the layout resource "color-wheel" and connect to the update stream
websocket_url = localhost('ws', 8000) + '/model/color-wheel/stream'
layout = purly.Layout(websocket_url)<jupyter_output><empty_output><jupyter_text>To do this we'll need a simple function that will create an HSL (hue, saturation, and lightness) color string. The function will accept the radius of the color picker wheel, and the x-y position of the mouse in order to select a color based on the angle around the circle, and distance from the center.<jupyter_code>def hsl(radius, x, y):
    """Return an HSL color string."""
    x -= radius
    y -= radius
    unit_radius = int((x ** 2 + y **2) ** 0.5) / radius
    degrees = int(math.atan2(x, y) * 180 / math.pi)
    return "hsl(%s, 100%%, %s%%)" % (degrees, unit_radius * 100)<jupyter_output><empty_output><jupyter_text>Next we'll need style up the the color wheel, and a selection indicator.<jupyter_code>radius = 50
wheel = layout.html('div')
wheel.style.update(
    height="%spx" % (radius * 2),
    width="%spx" % (radius * 2),
    backgroundColor="hsl(120, 100%, 50%)",
    borderRadius="50%",
)
selection = layout.html('div')
selection.style.update(
    height="20px",
    width="20px",
    backgroundColor="hsl(120, 100%, 50%)",
)
layout.children.append(wheel)
layout.children.append(selection)
layout.sync()
layout<jupyter_output><empty_output><jupyter_text>You should now see the color wheel and selector indicator in the output above!However when you mouse over the wheel nothing happens, so we'll need to hook into some mouse events to make the display animate. To do that requires the `onMouseMove` and `onClick` events which can be captures via the `on` decorator of the `wheel` element. The underlying logic of each is actually pretty simple:1. `onMouseMove`: if the mouse moves over the color wheel, then set the color wheel to the HSL color that corresponds to its x-y position.2. `onClick`: if the mouse clicks on the wheel, set the selection indicator to the corresponding HSL color.<jupyter_code>@wheel.on('MouseMove')
def cause_color_change(offsetX, offsetY):
    wheel.style["backgroundColor"] = hsl(50, offsetX, offsetY)

@wheel.on("Click")
def cause_color_select(offsetX, offsetY):
    selection.style["backgroundColor"] = hsl(50, offsetX, offsetY)<jupyter_output><empty_output><jupyter_text>Finally we'll need to serve up our event handlers in order to animate.<jupyter_code>layout.serve()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10356484326982175, 'fraction_numerical': 0.01782421634910879, 'mean_word_length': 5.188212927756654, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '489444', 'license': 'MIT', 'n_tokens_mistral': 1043, 'n_tokens_neox': 971, 'n_words': 377, 'path': 'examples/colors.ipynb', 'repo_name': 'rmorshea/purly', 'size': '3254'}