Masthash

#ThingUmbrella

Karsten Schmidt
3 days ago

This plea below is also the #1 reason why there isn't a code of conduct (yet?) for #ThingUmbrella. The pseudo-legalese tone of voice in all CoC I've read so far feels _very_ off-putting and IMHO doesn't make a project feel any more welcoming/inviting or safe.

Tolerance is something you're showing & exhibiting in your very actions/behaviors, not something you're explicitly stating/claiming/espousing to have in some document.

House rules. Ten commandments. Thou shalt not... I understand, and I'm in 100% agreement with what a CoC is trying to achieve in principle, but I'm super doubtful about this chosen approach/implementation/format/voicing vs. the actual desired expectations. I'm even more dubious about the passive-aggressive nudging of projects who don't have one (e.g. Github's "Community Standards" progress bar). To me, it is just a damn sad state of human affairs these kinds of documents (ALL of them pretty much saying the exact same things in more or less patronizing, bureaucratic, semi-corporate HR speech) are having to be explicitly spelled out over and over again, for each single project, and always for the same exact reasons, rather than assuming these norms as the default social standard...

Summa summarum: Be respectful, tolerant, assume the best, be open-minded, supportive and above all don't be a nazi/dick/misogynist etc.

Shit exceptions do of course exists, but really, how many projects/communities (as ratio) are choosing to passively accept or actively invite the opposite of the above? And aren't these outliers fairly easy to spot, early on, before any deeper engagement/contribution would be considered by newcomers?

What happened to us? How did we get here, and more importantly, how do we go _from_ here (with or without CoCs)? For the projects who have them, has the addition of a CoC _really_ (in practical terms) resulted in any tangible positive behavior selection/change/enforcement and was it _actually_ more meaningful than a mere rubberstamping exercise, i.e. the presence of such a document resulting in more than merely signalling a kind of sociopolitical belonging (and therefore a supposedly more welcoming/open attitude)?

https://mas.to/@TodePond/111149691826477201

#CodeOfConduct #OpenSource #Community #SocialBehavior

Karsten Schmidt
4 days ago

@nclslbrn Oh, this would be a really great addition and I can help you with the prep to keep it compatible and add metadata as with the other examples in the repo... Full credits to you of course, thank you!

Ps. I'm not quite sure why, but I only can see your replies via the #ThingUmbrella hashtag, not in my notifications though...

Karsten Schmidt
5 days ago

Thanks again (very much!) for all the open feedback to my recent #OpenSource & #ThingUmbrella musings! πŸ™πŸ™‡β€β™‚οΈ

Not wanting to go in circles, but many of the points raised are just describing symptoms (of being a relatively low popularity project, though one w/ pretty linear growth[1]) and it's really helpful to hear about them. But I am really looking & asking for ideas about possible pragmatic solutions (if you were in my shoes... but I'm guessing other project maintainers might be interested too). Other than pouring more time into creating learning/onboarding resources (which I've been doing more of lately), what else would you do? Throwing in the towel is a non-option...

For me there's this huge remaining disconnect between some of the feedback about these projects & examples being too advanced/complex/unapproachable and the sheer complexity of other JS projects (often with less docs/examples), the amount & complexity of brittle tooling with config hell, the plugin/plumbing culture of modern mainstream JS/TS webdev... #ThingUmbrella can and does largely sidestep and ignore most of this, but that's not seen as beneficial...? Also, what about the complexity & "alien" syntax/concepts/quirks of average Rust, Zig or Clojure projects? (How) are they self-selecting their audience?

I always thought of coding & learning like traveling. Only once you've encountered new concepts/philosophies, new languages, different cultures, different (maybe better, if initially strange) ways of doing things, you keep growing & moving forwards. thi.ng is filled to the brim with such: combining, expanding, remixing ideas and incorporating much of what I learned from earlier mistakes, from different languages & tools (not to mention contributing a plethora of fairly unique stuff itself). Personally (and of course this is super biased), but I've never felt more productive with any other set of tools. Period. My hope was they would attract more people sharing in this transdisciplinary attitude & journey. Have I really that badly miscalculated this audience is so limited? And, if so, why/how did the projects garner all these GH stars? Where/who are these people? As much as try, some of these things just aren't adding up...

What's become more clear here (as an intermediate step): It's about time to do another "State of thi.ngs" user survey again and I sincerly hope some of you will give your feedback once more in a more structured way...

[1] https://star-history.com/#thi-ng/umbrella&Date

Karsten Schmidt
5 days ago

@th0ma5 Thank you!!! These are all great points and food for thought. As for TypeScript - you don't have to use it to use these libs, it's all just vanilla JS once distributed (TS is optional). I do not know (anymore) how far along CLJS is with ES module support, but will try to find out (hollering @swannodette for wisdom)...

As for what can be composed - other than showing examples, I'm trying to think how else this could be communicated? Grateful for any ideas! With the amount of packages, there're simply too many possibilities to document and you should use the default assumption that most things are relatively straightforward composable & interoperable (where they make sense). For example:

https://thi.ng/transducers is used all over the place and probably one of (if not THE) most useful/composable package. Much larger selection of ops than you know from Clojure. Still constantly finding new uses for it... Maybe the GOAT of #ThingUmbrella πŸ˜‚

The https://thi.ng/vectors package (w/ 900+ functions) is used for anything geometry related, but also for colors, matrices, and due to its support for nD vectors, it's also very useful for statistics, time series, ML etc. Only uses/relies on native JS arrays (or typed arrays).

https://thi.ng/rstream is currently mostly used for UI related tasks (e.g. in combination with https://thi.ng/rdom), but itself has nothing to do with UI/frontend. Has multiple support packages define reactive state and compute graphs/pipelines/queries. Also heavily relies on transducers...

https://thi.ng/hiccup is what you know from CLJ, but provides much extended functionality and has several support packages to deal with HTML specifics (incl. parsing), SVG serialization, CSS, Markdown conversion etc. It's also used internally by quite a few other packages.

There're numerous packages just providing and dealing with different kinds of data structures (sets/graphs/heaps etc.), uses for which are generally well documented in CS literature...

In summary: I'm aware the sheer scale of #ThingUmbrella is daunting on first encounter, but it is what it is and the challenge now is how illustrate viable paths into that all...

Karsten Schmidt
5 days ago

#HowToThing #018 β€” Topological sorting, creating, querying and visualizing a task dependency graph using https://thi.ng/dgraph, https://thi.ng/dot & https://graphviz.org

Dependency graphs are super useful tools for a variety of use cases. Some examples:

Code generation/transpilation, e.g. used to emit code in correct order, detect cyclic references and to avoid duplicate definitions:
https://thi.ng/shader-ast
https://thi.ng/wasm-api-bindgen

Analyzing and visualizing project dependencies (not mobile friendly!): http://dependencies.thi.ng/

Visualizing reactive dataflow graph topologies:
https://github.com/thi-ng/umbrella/blob/develop/packages/rstream-query/README.md#visualizing-a-querys-dataflow-topology

Visualizing dispatch value hierarchies/relationships for polymorphic functions:
https://github.com/thi-ng/umbrella/blob/develop/packages/defmulti/README.md#dispatch-value-graph-visualization

Source code:
https://gist.github.com/postspectacular/4270801b1ffa98b381843ada4c59b0cb

If you have any questions about this topic or packages used here, please reply here or use the discussion forum (or issue tracker):

https://github.com/thi-ng/umbrella/discussions

#ThingUmbrella #Graph #GraphViz #DataViz #DataStructure #TypeScript #JavaScript #Tutorial

Screenshot of the 1st part of the linked TypeScript source code
Screenshot of the 2nd part of the linked TypeScript source code
Screenshot of the Graphviz-generated visualization of the example task graph, showing dependencies as arrows between tasks and already completed tasks highlighted in green.
Karsten Schmidt
1 week ago

#HowToThing #017 β€” (Re)Creating the https://thi.ng logo first as 2D geometry, then converting it to a SDF (Signed-distance field), then back again to geometry (via sampling the SDF at different distances and with warping) and finally serializing results to SVG...

This example gives a glimpse of the https://thi.ng/geom and https://thi.ng/geom-sdf packages to create & manipulate 2D geometries. Under the hood, this (once again) uses https://thi.ng/hiccup and https://thi.ng/hiccup-svg for SVG conversion...

As an aside, the colors come from one of the ~220 color palette presets of https://thi.ng/color-palettes (see readme for previews of all palettes)

Demo:
https://demo.thi.ng/umbrella/geom-sdf-logo/

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/geom-sdf-logo/src/index.ts

#ThingUmbrella #Geometry #SDF #SVG #TypeScript #JavaScript #Tutorial

Screenshot of the full TypeScript source for the linked example...
Screenshot of the resulting SVG output of the deformed thi.ng logo, consisting of colored shapes where the SDF has been sampled at 6 different distances
Karsten Schmidt
2 weeks ago

Earlier today I released a new version of https://thi.ng/fibers aka building blocks and operators for coroutine-based multitasking and alternative to async-await. It's one of the more recent packages, but also one which is quickly cementing itself as one of the most powerful & flexible tools of the whole #ThingUmbrella collection, similar to how https://thi.ng/transducers & https://thi.ng/rstream have done in other contexts...

Recent versions have included new helpers to improve interop between fibers and async functions and to simplify time-sliced processing of child tasks and/or iterables (incl. via transducers).

The attached code snippet shows an example excerpt of how this is used in the recent (and even more recently updated) #HowToThing Mastodon UI demo. See linked toot for demo link & fully commented source code...

https://mastodon.thi.ng/@toxi/111069280667363259

#TypeScript #JavaScript #Coroutines #Async

TypeScript code snippet (from an async function) showing how to wrap a fiber/task as promise and then waiting for its execution to complete:

// load recent messages
const rawMessages = await loadJSON(
	`${baseURL}/${account.id}/statuses?limit=50&exclude_replies=true&exclude_reblogs=true`
);

// split up message parsing/transformation over several frames,
// updating progress bar at each step
const transformedMessages = asPromise<Message[]>(function* () {
	const results: Message[] = [];
    // trigger & wait for time-sliced processing
	yield* timeSliceIterable(
		// create a (lazy) iterator of transformed messages
		iterator(transformMessage, rawMessages),
		// collect step-wise results, update progress
		(chunk) => {
			results.push(...chunk);
			progress.next(results.length / rawMessages.length);
		},
		// arbitrarily limit step duration (time slice) to 1ms
		1
	);
	return results;
});

// wait for task to finish & place results (transformed messages) into
// stream to trigger UI update
messages.next(await transformedMessages);
Karsten Schmidt
3 weeks ago

https://thi.ng/umbrella just reached 3k stars on #GitHub, w00t! 🀩πŸ₯³πŸ™

Btw. It's also #ReleaseFriday today, please check readme & changelogs!

#ThingUmbrella #OpenSource #TypeScript

Cropped screenshot of the GitHub UI, showing "3002 stargazers"
Karsten Schmidt
3 weeks ago

#HowToThing #016 β€” Building a small (and very incomplete!) Mastodon UI with #ThingUmbrella. Still, the following features are included so far and demonstrate:

- Looking up Mastodon account details & loading public messages for any given username
- Transforming JSON payloads with https://thi.ng/transducers
- HTML parsing, cleaning & rewriting via https://thi.ng/parse
- Reactive UI components via https://thi.ng/rstream & https://thi.ng/rdom
- Polymorphic (multiple-dispatch) functions via https://thi.ng/defmulti

UI features:

- Account details w/ header image, avatar, bio
- Media previews for images, gifv, videos
- Fullscreen modal overlay for images & alt text
- UI design heavily inspired by the amazing @phanpy (😍)

Alas, the code for this new example (#131) is too long & too split up for showing here in this format, but it's well documented and you can find it all linked below...

Demo:
https://demo.thi.ng/umbrella/mastodon-feed/

Source:
https://github.com/thi-ng/umbrella/tree/develop/examples/mastodon-feed/src

I hope this (and other parts) of this ongoing #HowToThing series are interesting to you. If so, please consider boosting and/or supporting my #OpenSource work via GitHub or Patreon. Thank you very much in advance!

https://github.com/sponsors/postspectacular
https://patreon.com/thing_umbrella

#TypeScript #JavaScript #Mastodon #UI #Reactive #FunctionalProgramming

Screenshot of the demo Mastodon UI
Karsten Schmidt
4 weeks ago

5 mins rendition of another variation of the synth: 120 bpm, 16th notes, 4 octaves, 75% probability...

#ThingUmbrella #Audio #Synth #Generative #DSP #TypeScript #JavaScript

Description in tweet. The video only contains the thi.ng logo as still image (main part is audio)
Karsten Schmidt
4 weeks ago

5 mins of generated audio of the example synth (see parent toot for context/code)...

#ThingUmbrella #Audio #Synth #Generative #DSP #TypeScript #JavaScript

Description in tweet. The video only contains the thi.ng logo as still image (main part is audio)
Karsten Schmidt
4 weeks ago

Just updated the synth & sequencer of the most recent #HowToThing example to be much more musical, added more params and switched to a faster oscillator. Now you can generate up to 5 mins of audio, choose note length, number of octaves and probability...

New audio example in the reply...

Demo:
https://demo.thi.ng/umbrella/render-audio/

Source:
https://github.com/thi-ng/umbrella/tree/develop/examples/render-audio/src

#ThingUmbrella #Audio #Synth #Generative #DSP #TypeScript #JavaScript

Screenshot of the synth with a minimal GUI for the various parameters...
Karsten Schmidt
1 month ago

#HowToThing #015 β€” A special one: Creating a polyphonic & multitimbral synth with stochastic sequencer to generate offline audio (*not* WebAudio!), rendered via fibers (co-routines) and exporting the result as WAV file. Each synth voice uses a randomized config & FX pipeline for each note played (osc β†’ adsr β†’ SVF β†’ filter delay line). Generated audio is attached.

Key packages used:
- https://thi.ng/dsp: Signal generators & effects
- https://thi.ng/dsp-io-wav: WAV file format export
- https://thi.ng/fibers: Time-sliced audio processing
- https://thi.ng/rdom: Reactive UI construction/updates

This project is also available as new example #130 in the thi.ng/umbrella monorepo (originally based on a workshop exercise @ University of Applied Sciences, Augsburg, Nov 2022)

Demo:
https://demo.thi.ng/umbrella/render-audio/

Source:
https://github.com/thi-ng/umbrella/tree/develop/examples/render-audio/src

(Code screenshots in reply this time... ✌️)

#ThingUmbrella #DSP #Audio #Synthesis #TypeScript #JavaScript #Tutorial

1 minutes of the generated audio with a still image (thi.ng logo) as video...
Karsten Schmidt
1 month ago

Currently very much still like dried glue (esp. at this resolution), but the overall idea was: Be like water, my friend... Next stop GLSL or maybe even WGSL!

#ThingUmbrella #TypeScript #FluidSim #Monochrome #GenerativeArt

Abstract still image of a moment of an experimental 2D pseudo fluid sim with (fake) viscous fingering and 4D simplex noise based turbulances applied to the velocity field...
Abstract still image of a moment of an experimental 2D pseudo fluid sim with (fake) viscous fingering and 4D simplex noise based texture & derived turbulances applied to the velocity fields...
Karsten Schmidt
1 month ago

#HowToThing #014 β€” Building a simple browser REPL UI for yesterday's Lispy S-expression mini language[1], using https://thi.ng/rdom and other usual suspects like https://thi.ng/rstream & https://thi.ng/transducers.

The language impl itself now also has local let-bindings, some more error checking, introspection and more examples of built-in functions...

Demo:
https://demo.thi.ng/umbrella/lispy-repl/

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/lispy-repl

(The attached source code image only shows the UI/REPL parts, the language implementation can be found in the above link...)

#ThingUmbrella #TypeScript #JavaScript #Lisp #FunctionalProgramming #Reactive #UI #REPL #DSL

[1] See yesterday's toot about building/using a mini DSL:
https://mastodon.thi.ng/@toxi/111006345413482231

Screenshot of the browser REPL in action
Screenshot of the 1st part of the TypeScript source code for the UI/REPL parts of the example
Screenshot of the 2nd part of the TypeScript source code for the UI/REPL parts of the example
Karsten Schmidt
1 month ago

PSA: The main #ThingUmbrella readme now contains a section with links to all #HowToThing mini-tutorials here on Mastodon (13 parts at time of writing):

https://github.com/thi-ng/umbrella/blob/develop/README.md#howtothing

(Note: Some of the code examples have received minor updates since initial publishing...)

Karsten Schmidt
1 month ago

#HowToThing #013 β€” Building a toy Lisp language and interpreter using the S-expression parser from https://thi.ng/sexpr and polymorphic multiple dispatch functions via https://thi.ng/defmulti. A small language like this can be useful for DSL purposes, user programming or for just learning about interpreters. The entire setup is highly customizable (incl. support for different kinds of S-expressions, see package readme).

Even this tiny example includes the following features: variadic math ops, ability to define new symbols/variables & functions, lexical scoping, numeric & string values...

Some example invocations are included at the end...

Source code:
https://github.com/thi-ng/umbrella/blob/develop/packages/sexpr/README.md#interpreter

(Update: Minor code simplifications, updated images)

#ThingUmbrella #TypeScript #JavaScript #Parser #DSL #Interpreter #Lisp #Tutorial

Screenshot of 1st part of the linked TypeScript source code...
Screenshot of 2nd part of the linked TypeScript source code...
Karsten Schmidt
1 month ago

#HowToThing #012 β€” Using https://thi.ng/hiccup-css and https://thi.ng/grid-iterators to generate pure CSS image transition/reveal effects.

Already had a few other glimpses of https://thi.ng/hiccup in this series, but here it's used to elegantly express & compose nested CSS rules (in addition to HTML), both either in the browser and/or serverside/offline. https://thi.ng/grid-iterators is used to generate the cell transition order. Please check the package readme for many more options...

This new example (#128) is also available as part of the thi.ng/umbrella monorepo now...

Demo:
https://demo.thi.ng/umbrella/hiccup-css-image-transition/
(Check the console for generated outputs)

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/hiccup-css-image-transition/src/index.ts

#ThingUmbrella #TypeScript #JavaScript #CSS #Animation

Screenrecording of the generated CSS image transition
Screenshot of 1st part of TypeScript source code of linked example...
Screenshot of 2nd part of TypeScript source code of linked example...
Karsten Schmidt
1 month ago

#HowToThing #011 β€” Creating a WebGL2 multi-pass shader pipeline using https://thi.ng/webgl to simulate 2D Cellular automata on the GPU. Here we use the classic Game of Life (yawn! ), but the setup allows for easily configurable rules/outcomes...

This new example (#127) is also available as part of the https://thi.ng/umbrella monorepo now...

Demo:
https://demo.thi.ng/umbrella/webgl-game-of-life/

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/webgl-game-of-life/src/index.ts

Related projects & reading:
https://thi.ng/cellular
https://demo.thi.ng/umbrella/cellular-automata/
https://demo.thi.ng/umbrella/wolfram/

Blog post:
https://github.com/thi-ng/blog/blob/main/2019/20190310-of-umbrellas-transducers-reactive-streams-pt3.md

#ThingUmbrella #CellularAutomata #Generative #TypeScript #JavaScript #GLSL #WebGL #Tutorial

Screenshot of the TypeScript source code of the linked example...
Screenshot of the Game of Life simulation in action...
Karsten Schmidt
1 month ago

Good morning. With the first 10 issues of #HowToThing done, here's a quick review and another kind request for feedback about which (of the vast amount of possible) topics you'd like to see/learn more about: Did you find any of the examples so far useful? Anything I can do to improve the format? Too small? Too basic? Too advanced?

To summarize, ongoing since August 2023: #HowToThing is a series of short posts demonstrating many different techniques, patterns, composition possibilities and use cases from across the https://thi.ng/ ecosystem. Each with heavily commented code (and with sometimes visual results)...

001: FPS counter with moving average
https://mastodon.thi.ng/@toxi/110898928550740865)

002: Sorting an array by potentially CPU-costly sort criteria
https://mastodon.thi.ng/@toxi/110904190618425908

003: Multiple key states and extracting commands via FSM
https://mastodon.thi.ng/@toxi/110934031101245644

004: Creating text-based plots to debug & visualize sequential data
https://mastodon.thi.ng/@toxi/110942967462856117

005: Barnsley fern IFS fractal
https://mastodon.thi.ng/@toxi/110946943031183702

006: Clustering arbitrary n-dimensional data using K-means
https://mastodon.thi.ng/@toxi/110955825785005618

007: Converting Google Maps bookmarks to KML
https://mastodon.thi.ng/@toxi/110961348580185768

008: CSV parsing into structured data & multi-plot SVG dataviz
https://mastodon.thi.ng/@toxi/110967240994840257

009: 2D canvas drawing & `threadLast()` dataflow operator
https://mastodon.thi.ng/@toxi/110972322869333970

010: Basic web app UI/DOM via Zig/WASM and thi.ng/wasm-api
https://mastodon.thi.ng/@toxi/110975292505640048

Preparing these examples takes quite a bit of time, so any feedback is highly appreciated...

#ThingUmbrella #TypeScript #JavaScript #Ziglang #OpenSource #Tutorial

Karsten Schmidt
1 month ago

#HowToThing #010 β€” Creating a basic web app with declarative UI/DOM creation via Zig/WebAssembly and the super extensible https://thi.ng/wasm-api and its https://thi.ng/wasm-api-dom add-on module, both hybrid TypeScript/Zig libraries. See alt text of images for details.

Demo:
https://demo.thi.ng/umbrella/howtothing-010/

Source code:
https://gist.github.com/postspectacular/08098359f75fa703a2cda64b1258a459

Also see the related project template (and its readme and comments) this example is based on:
https://github.com/thi-ng/tpl-umbrella-zig

Also, several more advanced (and interesting) hybrid Zig/TypeScript examples and extensive docs can be found in the https://thi.ng/wasm-api readme...

#ThingUmbrella #Ziglang #Zig #WebAssembly #WASM #TypeScript #JavaScript #WebDev #Tutorial

Fully commented Zig example source code (also see linked GitHub gist)...
Zig v0.11.0 build script to compile the example as WASM module. Launch via `zig build` (also see linked GitHub gist)...
Commented TypeScript source code to initialize the WASM module and the bridge APIs in the browser (also see linked GitHub gist)...
Screenshot of the minimal web UI created by the example. A headline says: "Hello Zig πŸ‘‹", below a button with a counter...
Karsten Schmidt
1 month ago

#HowToThing #009 β€” Basic 2D canvas drawing and using the `threadLast()` dataflow operator from https://thi.ng/compose for better legibility & comprehension of complex, nested call expressions, e.g. as used in functional data transformation pipelines.

In this example, we're transforming a stream of timestamps (from `requestionAnimationFrame()`), into animated 2D curve points, those into colored circle shapes and finally wrap all into a single group/scene for drawing.

A more basic intro example of the operator is included at the beginning... (#Clojure people will know the same as the `->>` macro)

Other packages used:

- https://thi.ng/dsp - points/curve generation via oscillators
- https://thi.ng/geom - shape types
- https://thi.ng/rstream - reactive stream creation
- https://thi.ng/rdom-canvas - reactive canvas creation & drawing
- https://thi.ng/transducers - data transformations

Demo:
https://demo.thi.ng/umbrella/rdom-canvas-basics/

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/rdom-canvas-basics/src/index.ts

#ThingUmbrella #FunctionalProgramming #TypeScript #JavaScript #Animation #Tutorial

1st part of the TypeScript source code of the example linked in the toot...
2nd part of the TypeScript source code of the example linked in the toot...
Screenrecording of the animation produced by the code example. 100 circles moving along a dynamically generated/animated curve
Karsten Schmidt
1 month ago

#HowToThing #008 β€” CSV parsing & filtering into structured data via https://thi.ng/csv and creating a multi-plot data visualization via https://thi.ng/viz (along with a range of other helpful packages for various side aspects).

The attached visualization shows a lin-log plot of new COVID cases between March 2020 - Dec 2021:

- Daily world total as line plot
- UK (red) and USA (blue) cases as interleaved bar plots

(All data from: https://ourworldindata.org/coronavirus)

Full source code:
https://gist.github.com/postspectacular/6a379a2bb8cd46e242163b9c9563522f

#ThingUmbrella #Transducers #TypeScript #JavaScript #DataViz #CSV #SVG #Tutorial

Screenshot of the 1st part of the TypeScript source code of the linked code example.
Screenshot of the 2nd part of the TypeScript source code of the linked code example.
Resulting lin-log chart showing daily new COVID19 cases as described in the toot and in the source code of the linked code example.
Karsten Schmidt
1 month ago

#HowToThing #007 β€” Using https://thi.ng/hiccup to convert #GoogleMaps "Saved Places" bookmarks (exported via Google Takeout) to KML, e.g. for importing to @organicmaps.

Usually, https://thi.ng/hiccup (and its various support packages) is used for defining HTML and/or UI components, but it's equally powerful for expressing many other hierarchical data structures, especially so when they're being serialized to an XML-like syntax (like KML, GPX, but also SVG...).

You can find more info, background & examples in the package readme...

Full source code:
https://gist.github.com/postspectacular/f69a3b0899ec4212fa59c3410536ee85

#ThingUmbrella #TypeScript #JavaScript #Mapping #KML #Tutorial

TypeScript source code of the KML converter (full version provided in linked GitHub gist)
Karsten Schmidt
1 month ago

#HowToThing #006 - Clustering arbitrary n-dimensional data using https://thi.ng/k-means and customizable distance functions and/or centroid strategies. For example, here to cluster 20 world cities into 5 groups based on their latitude/longitude...

Snippet source code:
https://gist.github.com/postspectacular/3a7970af491304fe7262e4701efa7d52

For a visual example (also fully commented) using thousands of items and SVG output, check out:

Demo:
https://demo.thi.ng/umbrella/kmeans-viz/

Source code:
https://github.com/thi-ng/umbrella/blob/develop/examples/kmeans-viz/src/index.ts

#ThingUmbrella #TypeScript #JavaScript #DataViz #Clustering #GIS #Tutorial

TypeScript source code of the linked world cities k-means clustering example. Link to source code is in the toot...
Screenshot of the other linked k-means example/visualization, showing a thousands of particles clustered into 18 groups, which are then shown in different colors and their convex hull shown as outlines
Karsten Schmidt
1 month ago

#HowToThing #005 β€” Elegantly compute the famous Barnsley fern IFS fractal using a mix of these packages:

- https://thi.ng/matrices: transformation matrix application
- https://thi.ng/random: weighted random selection
- https://thi.ng/pixel: floating point pixel buffer & conversions
- https://thi.ng/fibers: time-slicing of infinite IFS fractal process

As usual (for this series), there're more comments than code! Hth! πŸ€“

Also just added this as new example (#126):

Demo (will _slowly_ reveal due to chosen config):
https://demo.thi.ng/umbrella/ifs-fractal/

(Press `x` at any time to download the current frame)

Source code:
https://github.com/thi-ng/umbrella/tree/develop/examples/ifs-fractal

#ThingUmbrella #TypeScript #JavaScript #IFS #Fractal #Ferns #GenerativeArt #Monochrome #Tutorial

Generated result image of the Barnsley fern fractal using the same configuration as in the example
Alternative version of the Barnsley fern fractal using a slightly mutated configuration from that used in the example
Screenshot of TypeScript source code listing of the complete fractal generator. See link in toot for full source code...
Karsten Schmidt
1 month ago

Good Morning & welcome to #HowToThing #004 β€” Painlessly creating text-based plots to debug & visualize sequential data in a REPL-driven workflow. Here we're using https://thi.ng/dsp signal generators, but _any_ numeric array or iterable will work. Visualization via https://thi.ng/text-canvas (new versions of both packages have just been released...)

Source code:
https://gist.github.com/postspectacular/66d6b7c19612196c87cead5a6afd681d

#ThingUmbrella #TypeScript #JavaScript #AsciiArt #DataViz #DSP #Tutorial

Screenshot of a NodeJS REPL session with small code snippets to visualize several oscillator waveforms and an ADSR envelope as line plots or bar charts...
Karsten Schmidt
1 month ago

#ReleaseTuesday πŸš€ Forgot to mention in the previous toot that today also saw new releases (mainly maintenance, doc additions/updates, bugfixes, minor feature additions) of the following packages:

- https://thi.ng/associative
- https://thi.ng/hiccup-html
- https://thi.ng/rdom
- https://thi.ng/rstream
- https://thi.ng/strings
- https://thi.ng/transducers

Please see package changelogs for details...

#ThingUmbrella #TypeScript #OpenSource

Karsten Schmidt
1 month ago

#HowToThing #003 Tracking multiple key states and extracting high-level commands from key sequences via https://thi.ng/rstream & http://thi.ng/transducers-fsm. The key sequences are stored as a trie and matched via a transducer-based finite state machine.

Btw. The new example #125 of the https://thi.ng/umbrella monorepo shows an extended version of this approach...

Demo:
https://demo.thi.ng/umbrella/rdom-key-sequences/

Source:
https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-key-sequences

#ThingUmbrella #TypeScript #JavaScript #FSM #Transducers #Tutorial

TypeScript source code (part 1):

import { objectFromKeys } from "@thi.ng/associative";
import { $compile } from "@thi.ng/rdom";
import { fromDOMEvent, merge, trace } from "@thi.ng/rstream";
import { comp, filter, reducer, scan, sideEffect } from "@thi.ng/transducers";
import { fsm } from "@thi.ng/transducers-fsm";

// list of keys we're interested in
const MODIFIERS = ["shift", "control"];
const ALL_KEYS = ["w", "a", "s", "d", "z", "x", "k", ...MODIFIERS];

// object type for tracking multiple pressed keys
type KeyStates = Record<string, boolean>;

// type for finite state machine to recognize key sequences
type KeySeqState = { state: string; choices: Trie };

// recursive type for multi-key command sequences
// https://en.wikipedia.org/wiki/Trie
type Trie = { [id: string]: TrieData };
type TrieData = string | Trie;

// command sequences as nested data structure:
// - nested objects represent sub-sequences
// - strings values are command IDs
// e.g. ctrl+k ctrl+x => "open-explorer" command
const COMMANDS: Trie = {
	control: {
		a: "select-all",
		d: "duplicate",
		k: { w: "close all", s: "save-all", control: { x: "open-explorer" } },
		z: "undo",
		shift: { z: "redo" },
	},
	shift: { control: { z: "redo" } },
};

// create stream of key states by merging DOM event streams and attaching a
// transducer (`xform`) to transform the raw events into a stream of
// `KeyStates` objects...
TypeScript source code (part 2) - had issues pasting it here due to char limit, please download & use OCR to recover...
Screenshot of the linked example project
Karsten Schmidt
2 months ago

#HowToThing #002 β€” Sorting an array by potentially CPU-costly sort criteria. Along the way, this example also illustrates some basic https://thi.ng/geom functionality (e.g. #SVG export and polymorphic functions via https://thi.ng/defmulti)

Source code in alt text.

Second image shows generated SVG of the sorted shapes.

Ps. The `area()` function isn't heavy at all for the shapes used in the example, but it could/would be for more complex paths/polygons or when computing the area of entire shape hierarchies (aka nested `group()` shapes)...

#ThingUmbrella #TypeScript #JavaScript #Tutorial

import { sortByCachedKey } from "@thi.ng/arrays";
import { compareNumDesc } from "@thi.ng/compare";
import {
	area,
	asPolygon,
	asSvg,
	circle,
	rectWithCentroid,
	svgDoc,
	triangle,
} from "@thi.ng/geom";
import { writeFileSync } from "fs";

// create array of different shapes
const shapes = [
	// centered rect/square
	rectWithCentroid([0, 0], 100, { fill: "#8f0" }),
	// freeform triangle
	triangle([-100, 50], [0, 0], [100, 50], { fill: "#0ff" }),
	// circle w/ radius=150
	circle(150, { fill: "#f0f" }),
	// regular hexagon (sampled from a circle)
	asPolygon(circle(100, { fill: "#ff0" }), 6),
];

// all thi.ng/geom shapes have an implementation of
// the polymorpic `area` function
// see: https://docs.thi.ng/umbrella/geom/functions/area.html

// let's sort these shapes by descending area, so that largest shape is first.
// to avoid calling `area` (potentially expensive op) multiple times in a
// custom comparator during sorting, we can use `sortByCachedKey()` to only
// needing to compute the areas once and re-use these results...
// the custom comparator `compareNumDesc` is used to create descending order
sortByCachedKey(shapes, area, compareNumDesc);

// confirmation
console.log(shapes.map((x) => [x.type, area(x)]));

// convert to SVG for visual verification:
writeFileSync("002.svg", asSvg(svgDoc({}, ...shapes)));
Resulting SVG output β€” four shapes in back-to-front order: pink circle, yellow hexagon, green square, cyan triangle
Karsten Schmidt
2 months ago

Announcing #HowToThing, small code snippets illustrating useful patterns and use cases for various libraries/projects in the https://thi.ng ecosystem/anti-framework...

#HowToThing #001:
Build a FPS counter with moving average w/ https://thi.ng/transducers

Source code in alt text

(Ps. Have been trying to start similar stuff in the past on the birdsite, but let's see if I can control my attention and be more consistent this time... If you have any topic requests, please reply below [or via DM])

#ThingUmbrella #TypeScript #JavaScript #FunctionalProgramming #Transducers #Tutorial

import { fiber } from "@thi.ng/fibers";
import { benchmark, comp, map, movingAverage, step } from "@thi.ng/transducers";

// compose a FPS counter function from multiple transducers
// the `step` function is a wrapper for step-wise execution
const fps = step(
    comp(
        // measure time since last input
        // (the input value itself is irrelevant)
        benchmark(),
        // simple moving average (period=30)
        movingAverage(30),
        // convert time into frequency (frame per second), format
        map((x) => (1000 / x).toFixed(1) + " fps")
    )
);

// example usage
// (in browsers default execution of fibers is via requestAnimationFrame())
fiber(function* () {
    while (true) {
        // compute next step of FPS counter
        // since we're using a moving average of 30,
        // the first 29 frames will not yield any result (returns `undefined`)
        // the logical-OR (`||`) will then choose a fallback string
        const currFps = fps(0) || "[sampling]";
        console.log(currFps);
        // wait until next frame
        yield;
    }
}).run();

// see docs for more details:
// https://docs.thi.ng/umbrella/fibers/
// https://docs.thi.ng/umbrella/transducers/
Karsten Schmidt
2 months ago

Finished a major update[1] of the https://thi.ng/shader-ast-js shader-to-JavaScript transpiler & shader runtime and created a new little example[2], showing how to render a raymarching scene into a text canvas (aka HTML <pre> element) via https://thi.ng/text-canvas. Use the hotkeys to toggle options (and see transpiled shader source in console)...

Demo:
https://demo.thi.ng/umbrella/ascii-raymarch/

Source:
https://github.com/thi-ng/umbrella/blob/develop/examples/ascii-raymarch/src/index.ts

[1] This update completely avoids temporary allocations for all vector operations and uses pre-allocated pools now...
[2] This is example #124 in the https://thi.ng/umbrella repo

#ThingUmbrella #ASCIIArt #Raymarching #TypeScript #Demoscene

Screenrecording of the ASCII art rendered, animated raymarching scene (fly-through) of a colorful infinite 3D grid...
Karsten Schmidt
2 months ago

#ReleaseSaturday πŸš€ New version of https://thi.ng/random with new shared API additions and some minor internal perf improvements (see screenshot). This round also includes other minor performance updates for https://thi.ng/base-n and https://thi.ng/ksuid (mainly re: avoiding internal allocations)...

As always, please consult changelogs for more details...

#ThingUmbrella #TypeScript #OpenSource

Excerpt from the thi.ng/random package changelog:

3.6.1 (2023-08-12)
⏱ Performance improvements

    add/re-use internal buf for uuid() (6bf7f1d)
        avoid temp allocations (10% faster)

3.6.0 (2023-08-12)
πŸš€ Features

    add IRandom.minmaxUint() (6558eb1)
        clarify .minmaxInt() is for signed (i32)
        new .minmaxUint() is for unsigned (u32)
        add ARandom.minmaxUint()
    add IRandom.probability() (efdd49c)
        add impl for ARandom base class

⏱ Performance improvements

    increase Crypto default size to 1KB (a30075a)
    minor update randomBytesFrom() (770dbe5)
        switch loop direction
Karsten Schmidt
2 months ago

#ReleaseThursday As promised, a new version of https://thi.ng/fibers is out now and includes several new fiber operators/combinators and all the essentials for channel-based communication between processes/fibers (aka #CSP). The CSP channel supports arbitrary buffer sizes & implementations to achieve a range of blocking/non-blocking behaviors for reads/writes. And because all channel ops (read/write/close) are fiber-based, they can also be combined with all the other available operators, enabling some pretty powerful and expressive usage patterns...

More demos & tutorial forthcoming. Check the readme, API docs & examples and please report back with any feedback/questions/suggestions...

πŸ«ΆπŸš€

#ThingUmbrella #TypeScript #CooperativeMultitasking

Karsten Schmidt
2 months ago

After some friendly inquiry by @computersandblues, I spent a few hours today adding basic CSP (#CommunicatingSequentialProcesses) primitives for https://thi.ng/fibers and writing some preliminary documentation. I'm amazed how simple (and easy!) it was this time around (compared to https://thi.ng/csp) and it's giving me big hopes for the fiber based approach in general...

Readme section:
https://github.com/thi-ng/umbrella/blob/develop/packages/fibers/README.md#csp-primitives-communicating-sequential-processes

2-channel ping/pong example:
https://github.com/thi-ng/umbrella/blob/develop/packages/fibers/README.md#csp-pingpong-example

Source code & doc strings:
https://github.com/thi-ng/umbrella/blob/develop/packages/fibers/src/csp.ts

#ThingUmbrella #TypeScript #Coroutines #CSP #CooperativeMultitasking

Excerpt from readme:

"CSP primitives (Communicating Sequential Processes)

In addition to the operators above, the basic fiber implementation can also be used to construct other types of primitives, like these required for channel-based communication between processes. The package includes a fiber-based read/write channel primitive which can be customized with different buffer behaviors to control blocking behaviors and backpressure handling (aka attempting to write faster to a channel than values are being read, essentially a memory management issue).
Buffering behaviors

The following channel buffer types are included, all accepting a max. capacity and all implementing the required IReadWriteBuffer interface:

fifo: First in, first out. Writes to the channel will start blocking once the buffer's capacity is reached, otherwise complete immediately. Likewise, channel reads are non-blocking whilst there're more buffered values available. Reads will only block if the buffer is empty.

lifo: First in, last out. Read/write behavior is mostly the same as with fifo, with the important difference, that (as the name indicates), the last value written will be the first value read (i.e. stack behavior).

sliding: Sliding window buffer. Writes to the channel are never blocking! Once the buffer's capacity is reached, a new write will first expunge the oldest buffered value (similar to LRU cache behavior). Read behavior is the same as for fifo.
..."
TypeScript source code (ping/pong example):

import { channel, fiber, wait } from "@thi.ng/fibers";
import { ConsoleLogger } from "@thi.ng/logger";

// create idle main fiber with custom options
const app = fiber(null, {
    id: "main",
    logger: new ConsoleLogger("app"),
    terminate: true,
});

// create CSP channels (w/ default config)
const ping = channel<number>();
const pong = channel<number>();

// attach ping/pong child processes
app.forkAll(
    // ping
    function* () {
        let x: number | undefined;
        while (ping.readable()) {
            // blocking read op
            x = yield* ping.read();
            // check if channel was closed meanwhile
            if (x === undefined) break;
            console.log("PING", x);
            // blocking write op to other channel
            yield* pong.write(x);
            // slowdown
            yield* wait(100);
        }
    },
    // pong (very similar)
    function* () {
        let x: number | undefined;
        while (pong.readable()) {
            x = yield* pong.read();
            if (x === undefined) break;
            console.log("PONG", x);
            yield* ping.write(x + 1);
        }
    },
    // channel managment
    function* () {
        // kickoff ping/pong
        yield* ping.write(0);
        yield* wait(1000);
        // wait for both channels to close
        yield* ping.close();
        yield* pong.close();
    }
);
app.run();
Karsten Schmidt
2 months ago

Doing more experiments with the new https://thi.ng/fibers library for cooperative multitasking and very much loving some of the emerging code patterns and how they can simplify various things (e.g. state machines, animations, rhythmic triggers etc.). The ability to compose fibers, arbitrary fork & create child/sibling processes, then wait for (or cancel) them and communicate between them, provides so many possibilities. Similar to working with https://thi.ng/transducers or https://thi.ng/rstream, this all requires a bit of relearning & figuring out new (but often more simple) ways to approach an idea/problem. Glad I found my way back to this programming model and now without the headaches and perf/filesize issues I encountered with #Clojure's core.async back in 2013 (at least with the CLJS version)... I already had the https://thi.ng/csp library for similar purposes, but this new approach is much more flexible/powerful...

In this piece below, each of these animated rects runs in its own sub-process aka ES6 generators. Firefox on MBA M1 is running at a stable 60fps for up ~4200 fibers/processes, Chrome keeps 60fps until ~6000 fibers. Probably could go quite a bit higher when taking the canvas 2D rendering/overdraw/alpha blending out of the equation (or switching to WebGL)...

https://demo.thi.ng/umbrella/fiber-zoom/

Press `f` for fullscreen...

#ThingUmbrella #TypeScript

Screencapture of a randomized generative animation of thousands of colored, overlapping rectangles, growing, shrinking and fading out. Each shape is running in its own child process, recursively and semi-randomly spawing smaller subdivided rectangles...
Karsten Schmidt
2 months ago

#ReleaseFriday Among the multitude of minor updates and refactoring of various packages and some shared core types/interfaces (see readme & changelogs), the 40th #ThingUmbrella release of 2023 (already 555 in total!) is also featuring...

https://thi.ng/fibers - a new package providing a fiber process tree abstraction around ES6 generators for cooperative multitasking, incl. support for spawning & waiting for child processes, cancellation, event & error handling, logging, time slicing and various other highlevel operators to compose fibers (also via transducers). Please see readme, docs and the commented source code of this little #GenerativeArt example project for more insights:

Demo:
https://demo.thi.ng/umbrella/fiber-basics/

Source:
https://github.com/thi-ng/umbrella/blob/develop/examples/fiber-basics/src/index.ts

In this demo, each shape is animated in its own sub-process, recursively spawned from a single root fiber...

#TypeScript #OpenSource #Announcement

Screencapture of the aforementioned demo project showing a randomized generative animation of hundreds of colored, overlapping rectangles, growing, shrinking and fading out. Each shape is running in its own child process, recursively and semi-randomly spawing smaller subdivided rectangles.
Guido Schmidt
2 months ago

Got my hands back on some rdom/rstream based #thingumbrella UI tools to control a minimalistic turtle graphics drawing application.

#genart #MastoArt #GenerativeArt #CreativeCoding #CreativeToots