Ink Components

The goal of ink.js is to provide web-components for interactive scientific writing, reactive documents and explorable explanations. Included in ink.js are ways to create, update and display variables as text, equations and charts.

Tangled Cookies

ink.js is heavily inspired by tangle.js, updated to be use web-components! This means you can declaratively write your variables and how to display them in html markup. To get an idea of what that looks like, let's take the canonical example of Tangled Cookies - a simple reactive document to encourage you to not eat more than 42 cookies in one day.

When you eat cookies, you consume calories.

When you eat cookies, you consume calories.
That's of your recommended daily calories.


Examples
Components

Overview

Check out the table of contents on the right, or scroll on:

Dynamic Content
Variables (e.g. $x=$ ) and ways to change them using inline components (e.g. or ).
Text Content
Equations, code, figures, asides, call-outs and more.
Charts
TODO
Extensions
TODO

Getting started

Ink is based on web components, which create custom HTML tags so that they can make writing documents easier. To get started, copy the built javascript file to the head of your page.

<script src="/path/to/ink.js"></script> Note: This should be installable through npm

Taylor Series

The Taylor series of a real or complex-valued function $f(x)$ that is infinitely differentiable at a real or complex number $a$ is the power series f(x) \approx f(a) + \frac {f'(a)}{1!} (x-a) + \frac{f''(a)}{2!} (x-a)^2 + \frac{f^{(3)}(a)}{3!}(x-a)^3 + \cdots where $n!$ denotes the factorial of $n$ and $f^{(n)}(a)$ denotes the $n$th derivative of $f$ evaluated at the point $a$. In the more compact sigma notation, this can be written as \sum _{n=0}^{\infty }{\frac {f^{(n)}(a)}{n!}}(x-a)^{n}. The derivative of order zero of $f$ is defined to be $f$ itself and $(x - a)^0$ and $0!$ are both defined to be 1. When $a = 0$, the series is also called a Maclaurin series.

The sine function is closely approximated by its Taylor polynomial of degree 7 for a full period centered at the origin.
Try expanding the Taylor series: .


Demo

Variables should be able to choose their type, e.g. array. Variables should be able to control their bounds ?? Max should be overridden with a function :max="p_f_choices.length-1" Format should be a variable, but should still use the format that is defined. format=".2%" :map="p_f_array[p_f_pick]", not sure if this is a map, transform, or something else? Spark types, hist, spark line, etc.

According to Northern Gateway risk assessments, the probability of a tanker spill of any size would be about 0.4 per cent in any given year. The company estimated the return period (average interval between events) would be 250 years for a marine spill. Northern Gateway said the probability of a full-bore rupture on the oil pipeline would be 0.2 per cent in a given year, based on an estimated return period of 464 years.

National Energy Board & Canadian Environmental Assessment Agency (2013-12-19) Joint Review Panel

In order to gain insight into the potential risk of an oil spill, you can play with the parameters below! You can drag the blue highlighted numbers to adjust the interactive graph.

Let's say the probability of a spill is per year (Use Table 1). Let's say you are comfortable with a probability of not having a spill. With your risk tolerance and this probability, the pipeline should not be operated longer than years.

When the probability of a spill is the average interval between spills (the return period) as calculated by Northern Gateway is years. At years there is a chance there has already been an oil spill.

Figure 1: Probability of no spill when the failure rate is per year.

Table 1: Northern Gateway's summary of representative parameters for oil spill probabilities. Click a row to change the graph above.

Spill Type Return Period Annual Probability Page Reference
Oil Pipeline, Other Spills 4 years 25% page 67 (html)
Marine Terminal Spill 61 years 1.64% page 67 (html)
Oil Pipeline, Full-bore Rupture 240 years 0.417% page 67 (html)
Tanker Spill (any size) 250 years 0.4% page 60 (html)
Full-Bore Rupture, Oil Pipeline 464 years 0.2% page 60 (html)

Example Charts - Sin Wave

Amplitude, $A$:
Frequency, $f$:
Phase, $\varphi$:
y(t) = A \sin(2 \pi f t + \varphi)

Example chart - Drag Nodes

$A$:
$B$:
$x$:
$y$:

ArcTan2

The function $\operatorname{atan2}(y,x)$ (from "2-argument arctangent") is defined as the angle in the Euclidean plane, given in radians, between the positive x-axis and the ray to the point $(x,y)$. $\operatorname{atan2}(y,x)$ returns a single value $\theta$ such that $-\pi < \theta \le \pi$ and, for some $r > 0$, \begin{aligned} x&=r\cos \theta \\ y&=r\sin \theta \end{aligned}

r = \sqrt{x^2 + y^2} = $\theta$:°
$r$:
$x$:
$y$:

Example Charts - Adding Sin and Cos

Sin

Amplitude, $A$:
Frequency, $f$:
Phase, $\varphi$:

Cos

Amplitude, $A$:
Frequency, $f$:
Phase, $\varphi$:
y(t) = A \sin(2 \pi f t + \varphi)

Dynamic Content

If we have ranges for two variables:
X: , which is
Y: , which is
Or you can set the value directly in the text for X and Y .
The product of X and Y is .

Variables

TODO: These should be able to reference a different ink-scope TODO: Format should be a default and pulled through to other variables. This document has variables:

Variables need to be defined to drive your dynamic document, the ink-var web component can specify a name, description and a value.

<ink-var name="x" value="1"></ink-var>

These variables are hidden in the DOM, you can use a ink-var-list to see them all.

Reactive Variables

You can also create reactive variables which get execute a user-inputed string in an iframe with access to all other variables. Note here that the :value has a semi-colon to show that this should be executed to define the value.

<ink-var name="xSquared" :value="x * x"></ink-var> Properties of ink-var:
name
The variable to name to in the state, must follow javascript naming conventions for variables.
description
The variable description, useful for alt-text.
value
The value of the variable.
:value
Function to evaluate to update the value. If present, this will update the value anytime the state is changed.
format
A d3-format string. See the documentation.

Display Variables

To display an element create an ink-display, which will just render the named variable as text.

<ink-display name="x"></ink-display>

This is a number that is dynamic: .
Try setting the value of $x$ with the range input:

You can also transform the value of a variable before you format it. For example, you might want to say that the admission to a park is 'free' when the value == 0.

The park admission is .

You can also use this transform to say that the park admission is .
This is also quite useful if you want to use the transform to index into an array , in this case emoji array - but it could be numeric too!

Properties of ink-display:
name
The variable to name to in the state.
format
A d3-format string. See the documentation.
transform
Allows you to change or transform the value before formating: format(transform(value)). If the value is a string after transformation, it will not be formatted.

Controlling Variables

What gets slightly more exciting is when you can bring these together with inputs that can be ranges or dynamic text elements that you can drag.

<ink-dynamic name="x"></ink-dynamic>

This allows you to set the value of $x$ inline: or $y=$.
Notice how it is linked to the above ink-range and ink-display.
You can also add inside of the html tag, to have custom formatting that also is dynamic.
For example, °C, the °C is inside of the <ink-dynamic> tags, so it is also has a blue underline.

You can also create ranges, as see above, notice that we can create a lot of these and name to different values.

<ink-range name="x"></ink-range>

$x_{1.0}:$
$y_{1.0}:$
$y_{0.5}:$

Properties:
name
The variable to name to in the state, setting this will set :value="name" and bind="{name:value}".
value
The numeric value of the control. Can also be set by :value.
bind
A dictionary that should set variables: (value) => {x: value}.
format
A d3-format string. See the documentation.
min
Minimum of the range.
max
Maximum of the range.
step
Step size.
sensitivity
Multiplier on pixels dragged for the dynamic text input.
transform
Allows you to change or transform the value before formating: format(transform(value)). If the value is a string after transformation, it will not be formatted.
periodic
When dragged start past min/max connect the range by cycling through again.

name, :value & bind

There are times where you want more control over how your data gets displayed, updated or informs other variables. There are three properties to consider: name, :value, and bind. The most common use is through the name property, which is used to both set the control's value, and bind the change to the named variable. This amounts to a two way connection: <ink-dynamic name="x" ></ink-dynamic> When the variable x updates, the value is set, and when the control updates the value, the result updates the variable! Under the hood, when name is defined, the :value and the bind functions are automatically set. <ink-dynamic :value="x" bind="{x: value}" ></ink-dynamic> As with other properties, the : syntax for the value property recomputes every time there is a change. For example, if you put :value="x" then anytime the variable x changes, the value of the control updates. However, this is not the case in reverse! You have to explicitly bind the control to the variable (or variables) you want to update. This is done using a JSON dictionary of the form {variable: value}. Note that you can update multiple variables at a time. If you choose to explicitly set these, and not just use the name property, you can do some interesting things!

Coordinate Transformation

A good example of this is changing from a radial coordinate system to Cartesian. In this case we will have two variables:
Cartesian Coordinate System

$x$
$y$

Radial Coordinate System
$r$
$\theta$
°

Cartesian Update

<ink-dynamic name="x"></ink-dynamic> This gets rewritten and is equivalent to: <ink-dynamic :value="x" bind="{ x: value }"></ink-dynamic>

Radius Update <ink-dynamic :value="Math.sqrt(x*x + y*y)" bind="{ x: value * Math.cos(Math.atan2(y, x)), y: value * Math.sin(Math.atan2(y, x)) }"></ink-dynamic> Theta Update <ink-dynamic :value="Math.atan2(y, x)" bind="{ x: Math.sqrt(x*x + y*y) * Math.cos(value), y: Math.sqrt(x*x + y*y) * Math.sin(value) }"></ink-dynamic>


Text Content

Equations

x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}

Use the eqn.math property to change the math dynamically:

Drag me to expand the Taylor Series:

Code and demos

>>> import numpy as np >>> a = np.arange(15).reshape(3, 5) >>> a array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])

Most of the content on this page uses the <ink-demo> component:

This is a demo of a demo!!

Figures

Setup of a DC resistivity survey.

Asides

Ink has Tufte style sidenotes to add sarcastic or poignant insights. These asides can include figures and equations.

Sometimes you need to say things on the side. Which is over here!

Warning: This may get peoples attention.

Tiles

And this is just text.

SVG Web Component Charts

The render function of the chart loops through all of the children and renders the SVG template. Each ink-chart child has to return an SVG namespaced string to add to the chart. In this way, they keep the same ordering as the dom

render() { return html` <svg width="${this.width}" height="${this.height}"> ${this.children.map(child =>{ return child.renderSVG(this); })} </svg> `; }

Each child component has a renderSVG function that returns an svg template string.

Ink Chart Components:
ink-chart-circle
An SVG circle that can control x and y location, color, radius and other standard svg circle properties..
ink-chart-path
An SVG path that can control data (an array of [x, y]), stroke and other standard svg path properties..
ink-chart-text
An SVG text that can control x and y location, color and other standard svg text properties..
ink-chart-eqn
An SVG path that is parameterized by a function (eqn) and controls stroke, color and other standard svg path properties..
ink-chart-node
An interactive node that can be dragged. Can control stroke, color and other standard svg circle properties..

Ink Chart Equations

Need to show scatter points for the eqn.

The ink-chart-eqn component allows you to create dynamic lines or points based on an equation. This allows you to create and show equations like (x) => Math.sin(x). You can also parameterize the function over x, y or t. When parameterizing in terms of t you must supply a domain (e.g. [0, 1]) and the function should return a length-two list. Both x and y parameterizations provide the other coordinate so the function should only return a number.


Amplitude, $A$:
Start: End: