From 6cadd09b4e74dd821c0f51996d33992a615f8bdb Mon Sep 17 00:00:00 2001 From: osmarks Date: Fri, 11 Oct 2024 20:17:33 +0100 Subject: [PATCH] new script --- README.md | 6 ++++- captive_portal.py | 8 +++--- cool-effect.glsl | 35 ++++++++++++++++++++++++++ portable_monitor_wallmount.py | 21 ++++++++++++++++ square-law gravity - physics test.html | 3 ++- weight_painter.py | 34 +++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 cool-effect.glsl create mode 100644 portable_monitor_wallmount.py create mode 100644 weight_painter.py diff --git a/README.md b/README.md index 12008e0..495c979 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,8 @@ This comes with absolutely no guarantee of support or correct function, although * `StringGroup.hs` - native Haskell strings are only a monoid, so I made an improved version which forms a group instead. * `arithmetic_coder.py` - arithmetic coding implementation apart from the fact that it doesn't work properly (it doesn't write enough digits for some reason I haven't worked out). * `bmp280_prometheus.py` - read BMP280 temperature/pressure sensors and export as Prometheus metrics. -* `captive_portal.py` - automatically fill in captive portal forms (WIP). \ No newline at end of file +* `captive_portal.py` - automatically fill in captive portal forms (WIP). +* `scd4x_prometheus.py` - read SCD4x temperature/humidity/CO2 sensors and export as Prometheus metrics. +* `weight_painter.py` - paint arbitrary images into neural network weight matrices. Uses a permutation, so the distribution is preserved so training dynamics remain unaffected (so long as the network doesn't care about organization below the weight matrix level - this is not safe for attention heads etc). +* `cool-effect.glsl` - a nice effect I made by accident whilst trying to make a cooler one. +* `portable_monitor_wallmount.py` - very simple CADQuery script which generates a frame for my portable monitor's top/bottom bezels so it can be stuck to the wall and slid out easily. diff --git a/captive_portal.py b/captive_portal.py index a7d554e..c72747e 100644 --- a/captive_portal.py +++ b/captive_portal.py @@ -66,7 +66,7 @@ dns_server = get_dns() print("DNS server", dns_server) adapter = CustomDNSAdapter(dns_server) session.mount("http://", adapter) -session.mount("https://", adapter) +session.mount("https://", adapter) session.verify = False session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"}) @@ -90,7 +90,7 @@ def handle_response(response): queue_ext.insert(0, href) else: queue_ext.append(href) - + for form in soup.find_all("form"): fields = {} @@ -108,7 +108,7 @@ def handle_response(response): k, v = repeat fields[k] = v continue - + fieldtype = None for ty in FIELDTYPES: if ty in name.lower(): @@ -155,7 +155,7 @@ def handle_response(response): queue.extend(x for x in queue_ext if x not in tried) while True: - response = session.get("https://crosscountrywifi.co.uk/connect") + response = session.get(DETECTPORTAL_URL) if response.text == DETECTPORTAL_CONTENT: print("OK") raise SystemExit(0) diff --git a/cool-effect.glsl b/cool-effect.glsl new file mode 100644 index 0000000..4ae453d --- /dev/null +++ b/cool-effect.glsl @@ -0,0 +1,35 @@ +float lscale = 0.1; +float lscaleh = 0.05; + +float dfn(float x) { + return abs(mod(x - lscaleh, lscale) - lscaleh) / lscale; +} + +float dfn_nonlin(float x) { + //return x; + if (x < 0.1) return 0.3; + else return 0.0; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + // -1 to 1 ish maybe + vec2 uv = 2.0*fragCoord/iResolution.xx - vec2(1.0,1.0); + + vec3 ldir = vec3(1.0, uv); + vec3 l0 = vec3(0.0); + + float n = 1.0; + vec3 bri = vec3(0.0); + + for (float n = 1.0; n <= 3.0; n += 1.0) { + vec3 p0 = vec3(n, 0.0, 0.0); + float lam = (p0 - l0).x / ldir.x; + vec3 isect = l0 + ldir * lam; + //vec3 isect = vec3(0.0, uv); + bri += vec3(0.0, dfn_nonlin(dfn(isect.y)) + dfn_nonlin(dfn(isect.z)), 0.0); + } + + // Output to screen + fragColor = vec4(bri,1.0); +} diff --git a/portable_monitor_wallmount.py b/portable_monitor_wallmount.py new file mode 100644 index 0000000..bbde18a --- /dev/null +++ b/portable_monitor_wallmount.py @@ -0,0 +1,21 @@ +import cadquery as cq + +LENGTH = 250 +BEZEL_THICKNESS = 14 +MONITOR_THICKNESS = 9 +MOUNT_THICKNESS = 1.0 + +pts = [ + (-MOUNT_THICKNESS, -MOUNT_THICKNESS), + (-MOUNT_THICKNESS, MONITOR_THICKNESS + MOUNT_THICKNESS), + (BEZEL_THICKNESS, MONITOR_THICKNESS + MOUNT_THICKNESS), + (BEZEL_THICKNESS, MONITOR_THICKNESS), + (0, MONITOR_THICKNESS), + (0, 0), + (BEZEL_THICKNESS, 0), + (BEZEL_THICKNESS, -MOUNT_THICKNESS), +] + +result = cq.Workplane("XY").polyline(pts).close().extrude(LENGTH).edges("|Z").chamfer(0.3) + +cq.exporters.export(result, "/tmp/result.stl") diff --git a/square-law gravity - physics test.html b/square-law gravity - physics test.html index 6c66504..6ebfc5a 100644 --- a/square-law gravity - physics test.html +++ b/square-law gravity - physics test.html @@ -47,7 +47,8 @@ const F = vsum(objects.filter(x => x !== object).map(x => vscale(G * (object.m * x.m) * (vmag(vsub(object.x, x.x)) ** 2), vnorm(vsub(object.x, x.x))) )) - object.v = vadd(object.v, vscale(timestep, vscale(1 / object.m, F))) + const a = vscale(1 / object.m, F) + object.v = vadd(object.v, vscale(timestep, a)) //console.log(F, object.x, object.v) } } diff --git a/weight_painter.py b/weight_painter.py new file mode 100644 index 0000000..ee4dc62 --- /dev/null +++ b/weight_painter.py @@ -0,0 +1,34 @@ +import torch +from PIL import Image +import math +import numpy + +def paint(im: Image.Image, weight: torch.Tensor): + device = weight.device + weight = weight.view(-1) + dim = math.floor(math.sqrt(weight.shape[0])) + weight = weight[:dim * dim] + paint = torch.tensor(numpy.asarray(im.resize((dim, dim)).convert("L"))).to(device).reshape(-1) + permutation = torch.argsort(paint) + inverse_permutation = torch.argsort(permutation) + sorted_weights, _ = torch.sort(weight) + new_weight = sorted_weights[inverse_permutation] + weight[:] = new_weight + +def render(weight: torch.Tensor): + weight = weight.view(-1) + dim = math.floor(math.sqrt(weight.shape[0])) + weight = weight[:dim * dim] + weight_np = weight.cpu().numpy().reshape((dim, dim)) + weight_np += weight_np.min() + weight_np /= weight_np.max() - weight_np.min() + weight_np *= 255 + return Image.fromarray(weight_np.astype(numpy.uint8)) + +if __name__ == "__main__": + im = Image.open("test.png") + weight = torch.randn(256, 256) + paint(im, weight) + out_im = render(weight) + out_im.show() + out_im.save("out.png")