--- title: "vsketch and NixOS" date: 2023-07-09T15:26:24+02:00 tags: - NixOS - Plotting - vsketch summary: > Adventures with vsketch, axidraw and NixOS. --- # vsketch and NixOS I like to plotter. I like to draw pictures with my [axidraw](https://axidraw.com/) and ogle with the [terrapen](https://terrapen.xyz/products/terrapen-a2-pen-plotter) . I had a few runs on using [vsketch](https://vsketch.readthedocs.io/en/latest/) in [NixOS](https://nixos.org) but because I don't know much about Python, I had never found enough time to make [vsketch](https://vsketch.readthedocs.io/en/latest/) work under NixOS. Same holds for the [axidraw cli](https://axidraw.com/doc/cli_api/#introduction). But lately I got introduced to [pipenv](https://pipenv.pypa.io/en/latest/) which made everything possible and very easy. Setup ----- I simple use a combination of `direnv` `shell.nix` , `steam-run` and `pipenv` to make everything work. ### shell.nix The shell nix is called by `direnv` simply by putting ```text-plain use nix ``` in the repositories `.envrc` file. In the `shell.nix` I simple define a all packages I need and override the `steam-run` binary to add some package. Getting to this point, was a bit fiddly, but once it works, it works :D This is my `shell.nix` ```text-plain { pkgs ? import { } }: pkgs.mkShell { buildInputs = let steamrun = (pkgs.steam.override { extraPkgs = pkgs: [ (pkgs.python3.withPackages (ps: with ps; [ matplotlib pyside6 setuptools scikitlearn toml ])) pkgs.qt6.qtbase ]; extraLibraries = pkgs: [ pkgs.libkrb5 ]; }).run; in [ (pkgs.writers.writeDashBin "vsk" '' ${steamrun}/bin/steam-run pipenv run vsk "$@" '') (pkgs.writers.writeDashBin "axicli" '' ${steamrun}/bin/steam-run pipenv run axicli "$@" '') (pkgs.writers.writeDashBin "pipenv-shell" '' ${steamrun}/bin/steam-run pipenv shell '') ]; } ``` ### Pipenv Now `pipenv` has all needed dependencies for it's thing to do. But we need to set up `pipenv` itself as well, of course. Here is my `Pipfile`: ```text-plain [[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] vsketch = {editable = true, git = "https://github.com/abey79/vsketch"} axicli = {file = "https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip" } [dev-packages] [requires] python_version = "3.10" python_full_version = "3.10.11" ``` Now I can run ```text-plain pipenv install ``` and magically the shell command `vsk` (which is defined in the `shell.nix`) works like charm. My first sketch --------------- After running ```text-plain vsk init SimpleRings ``` I could instantly start fiddling around with the code. I'm amazed how fast my development cycle was. I could instantly see results, and play around with seed and parameters. And once I liked something. I can just hit **Like** and it will be saved as svg. Here is my first script + some screenshots and photos of the results: ```text-plain import vsketch class SimpleRingsSketch(vsketch.SketchClass): amount = vsketch.Param(3) space = vsketch.Param(30, min_value=10) min_radius = vsketch.Param(30, min_value=1) base_rotation = vsketch.Param(1) show_rings = vsketch.Param(True) show_rings_randomly = vsketch.Param(True) show_lines = vsketch.Param(True) def draw(self, vsk: vsketch.Vsketch) -> None: vsk.size("a4", landscape=False) # vsk.scale("mm") # height and width are in pixels (not mm) max_radius = min(vsk.height / 2, vsk.width / 2) - self.space for i in range(self.amount): radius = vsk.random(self.min_radius, max_radius) amount_of_lines = int(vsk.random(1, radius)) line_length = vsk.random(1, 20) circle_line_height = vsk.random(1, line_length) # vsk.random() consumes the seed, so we have to consume it in every step, other changing the # options would result in different results in the other routines. if vsk.random(0, 1) > 0.5 or not self.show_rings_randomly: if self.show_rings: vsk.circle(0, 0, radius - circle_line_height, mode="radius") if not self.show_lines: continue vsk.rotate(self.base_rotation, degrees=True) with vsk.pushMatrix(): angle = 360.0 / amount_of_lines for j in range(0, amount_of_lines): vsk.rotate(angle, degrees=True) vsk.line(0, radius, 0, radius - line_length) def finalize(self, vsk: vsketch.Vsketch) -> None: vsk.vpype("linemerge linesimplify reloop linesort") if __name__ == "__main__": SimpleRingsSketch.display() ``` {{< card >}} {{
}} {{< /card >}} {{< card >}} {{
}} {{
}} {{< /card >}}