@explorable-viz/fluid 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluid/fluid/lib/graphics.fld +246 -221
- package/dist/fluid/fluid/lib/matrix.fld +44 -41
- package/dist/fluid/fluid/lib/stats.fld +86 -75
- package/dist/fluid/shared/fluid.mjs +7830 -8585
- package/dist/fluid/shared/load-figure.js +7666 -7835
- package/dist/fluid/shared/webtest-lib.js +1479 -1479
- package/package.json +1 -1
- package/website/article/css/styles.css +3 -35
- package/website/article/css/view-styles.css +1 -5
- package/website/article/fluid/1805.02474v1-10.fld +2 -2
- package/website/article/fluid/scigen.fld +4 -0
- package/website/article/scigen-1805.02474v1-10/index.html +4 -0
- package/website/article/test.mjs +1 -4
- package/website/article/font/GraphikLight.woff2 +0 -0
- package/website/article/font/GraphikLightItalic.woff2 +0 -0
- package/website/article/font/GraphikMedium.woff2 +0 -0
- package/website/article/font/GraphikMediumItalic.woff2 +0 -0
- package/website/article/font/OdiseanTech.woff2 +0 -0
@@ -1,221 +1,246 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
1
|
+
def coords(Group(gs)): Point(0, 0)
|
2
|
+
def coords(Rect(x, y, _, _, _)): Point(x, y)
|
3
|
+
def coords(String(x, y, _, _, _)): Point(x, y)
|
4
|
+
def coords(Viewport(x, y, _, _, _, _, _, _, _)): Point(x, y);
|
5
|
+
|
6
|
+
def get_x(g):
|
7
|
+
def Point(x, _): coords(g);
|
8
|
+
|
9
|
+
x;
|
10
|
+
|
11
|
+
def get_y(g):
|
12
|
+
def Point(_, y): coords(g);
|
13
|
+
|
14
|
+
x;
|
15
|
+
|
16
|
+
def set_x(x, Group(gs)):
|
17
|
+
error("Group has immutable coordinates")
|
18
|
+
def set_x(x, Rect(_, y, w, h, fill)):
|
19
|
+
Rect(x, y, w, h, fill)
|
20
|
+
def set_x(x, String(_, y, str, anchor, baseline)):
|
21
|
+
String(x, y, str, anchor, baseline)
|
22
|
+
def set_x(x, Viewport(_, y, w, h, fill, margin, scale, translate, g)):
|
23
|
+
Viewport(x, y, w, h, fill, margin, scale, translate, g);
|
24
|
+
|
25
|
+
def dimensions2((Point(x1, y1), Point(x2, y2))):
|
26
|
+
Point(max(x1, x2), max(y1, y2));
|
27
|
+
|
28
|
+
def dimensions(Group(gs)):
|
29
|
+
foldl(curry(dimensions2), Point(0, 0), map(coords_op, gs))
|
30
|
+
def dimensions(Polyline(ps, _, _)):
|
31
|
+
foldl(curry(dimensions2), Point(0, 0), ps)
|
32
|
+
def dimensions(Rect(_, _, w, h, _)): Point(w, h)
|
33
|
+
def dimensions(String(_, _, _, _, _)): Point(0, 0)
|
34
|
+
def dimensions(Viewport(_, _, w, h, _, _, _, _, _)): Point(w, h)
|
35
|
+
def coords_op(g):
|
36
|
+
def (Point(x, y), Point(w, h)):
|
37
|
+
prod(coords, dimensions, g);
|
38
|
+
|
39
|
+
Point(x + w, y + h);
|
40
|
+
|
41
|
+
def width(g):
|
42
|
+
def Point(w, _): dimensions(g);
|
43
|
+
|
44
|
+
w;
|
45
|
+
|
46
|
+
def height(g):
|
47
|
+
def Point(_, h): dimensions(g);
|
48
|
+
|
49
|
+
h;
|
50
|
+
|
51
|
+
def spaceRight(z, sep, gs):
|
52
|
+
zipWith(set_x, iterate(length(gs), (+)(sep), z), gs);
|
53
|
+
|
54
|
+
def colours1: [
|
55
|
+
"#66c2a5",
|
56
|
+
"#a6d854",
|
57
|
+
"#ffd92f",
|
58
|
+
"#e5c494",
|
59
|
+
"#fc8d62",
|
60
|
+
"#b3b3b3",
|
61
|
+
"#8da0cb",
|
62
|
+
"#e78ac3"
|
63
|
+
];
|
64
|
+
|
65
|
+
def colours2: [
|
66
|
+
"#e41a1c",
|
67
|
+
"#377eb8",
|
68
|
+
"#4daf4a",
|
69
|
+
"#984ea3",
|
70
|
+
"#ff7f00",
|
71
|
+
"#ffff33",
|
72
|
+
"#a65628",
|
73
|
+
"#f781bf"
|
74
|
+
];
|
75
|
+
|
76
|
+
def scaleToWidth(w, Rect(x, y, _, h, fill)):
|
77
|
+
Rect(x, y, w, h, fill)
|
78
|
+
def scaleToWidth(w, Viewport(x, y, w0, h, fill, margin, Scale(x_scale, y_scale), translate, g)):
|
79
|
+
def scale:
|
80
|
+
Scale((x_scale * w) / w0, y_scale);
|
81
|
+
|
82
|
+
Viewport(x, y, w, h, fill, margin, scale, translate, g);
|
83
|
+
|
84
|
+
def stackRight(sep, gs):
|
85
|
+
map(scaleToWidth(1 - sep), spaceRight(sep / 2, 1, gs));
|
86
|
+
|
87
|
+
def groupRight(sep, gs):
|
88
|
+
Viewport(0, 0, length(gs), maximum(map(height, gs)), "none", 0, Scale(1, 1), Translate(0, 0), Group(stackRight(sep, gs)));
|
89
|
+
|
90
|
+
def tickEvery(n):
|
91
|
+
def m:
|
92
|
+
floor(logBase(10, n));
|
93
|
+
|
94
|
+
if n <= 2 * 10 ** m: 2 * 10 ** (m - 1)
|
95
|
+
else: 10 ** m;
|
96
|
+
|
97
|
+
def axisStrokeWidth: 0.5
|
98
|
+
def axisColour: "black"
|
99
|
+
def backgroundColour: "white"
|
100
|
+
def defaultMargin: 24
|
101
|
+
def markerRadius: 3.5
|
102
|
+
def tickLength: 4;
|
103
|
+
|
104
|
+
def tick(Horiz, colour, len):
|
105
|
+
Line(Point(0, 0), Point(0, 0 - len), colour, axisStrokeWidth)
|
106
|
+
def tick(Vert, colour, len):
|
107
|
+
Line(Point(0, 0), Point(0 - len, 0), colour, axisStrokeWidth);
|
108
|
+
|
109
|
+
def label(Horiz, x, distance, str):
|
110
|
+
String(x, (0 - distance) - 4, str, "middle", "hanging")
|
111
|
+
def label(Vert, x, distance, str):
|
112
|
+
String(0 - distance, x, str, "end", "central");
|
113
|
+
|
114
|
+
def labelledTick(orient, colour, len, str):
|
115
|
+
Group([
|
116
|
+
tick(orient, colour, len),
|
117
|
+
label(orient, 0, len, str)
|
118
|
+
]);
|
119
|
+
|
120
|
+
def mkPoint(Horiz, x, y): Point(y, x)
|
121
|
+
def mkPoint(Vert, x, y): Point(x, y);
|
122
|
+
|
123
|
+
def axis(orient, x, start, end):
|
124
|
+
def tickSp:
|
125
|
+
tickEvery(end - start)
|
126
|
+
def firstTick:
|
127
|
+
ceilingToNearest(start, tickSp)
|
128
|
+
def lastTick:
|
129
|
+
ceilingToNearest(end, tickSp)
|
130
|
+
def n:
|
131
|
+
floor((end - firstTick) / tickSp) + 1
|
132
|
+
def ys:
|
133
|
+
iterate(n, (+)(tickSp), firstTick)
|
134
|
+
def ys:
|
135
|
+
match firstTick > start:
|
136
|
+
case True: start :| ys
|
137
|
+
case False: ys
|
138
|
+
def ys:
|
139
|
+
match lastTick > end:
|
140
|
+
case True:
|
141
|
+
concat2(ys, [lastTick])
|
142
|
+
case False: ys
|
143
|
+
def ps:
|
144
|
+
map(mkPoint(orient, x), ys)
|
145
|
+
def ax:
|
146
|
+
Group([
|
147
|
+
Line(head(ps), last(ps), axisColour, axisStrokeWidth),
|
148
|
+
Polymarkers(ps, flip(map, ys, compose(labelledTick(orient, axisColour, tickLength), numToStr)))
|
149
|
+
]);
|
150
|
+
|
151
|
+
(ax, lastTick);
|
152
|
+
|
153
|
+
def catAxis(orient, x, catValues):
|
154
|
+
def ys:
|
155
|
+
iterate(length(catValues) + 1, (+)(1), 0)
|
156
|
+
def ps:
|
157
|
+
map(mkPoint(orient, x), ys);
|
158
|
+
|
159
|
+
Group([
|
160
|
+
Line(head(ps), last(ps), axisColour, axisStrokeWidth),
|
161
|
+
Polymarkers(tail(ps), map(const(tick(orient, axisColour, tickLength)), catValues)),
|
162
|
+
Polymarkers(flip(map, tail(ps), (lambda Point(x, y): Point(x - 0.5, y))), map(label(orient, -0.5, 0), catValues))
|
163
|
+
]);
|
164
|
+
|
165
|
+
def viewport(x_start, x_finish, y_finish, margin, gs):
|
166
|
+
Viewport(0, 0, x_finish - x_start, y_finish, backgroundColour, margin, Scale(1, 1), Translate(0 - x_start, 0), Group(gs));
|
167
|
+
|
168
|
+
def lineChart(withAxes, colours, x_start, data):
|
169
|
+
def xs: map(fst, data)
|
170
|
+
def nCat:
|
171
|
+
length(snd(head(data)));
|
172
|
+
|
173
|
+
def plot((n, colour)):
|
174
|
+
def ps:
|
175
|
+
map((lambda (x, kvs): Point(x, snd(nth(n, kvs)))), data);
|
176
|
+
|
177
|
+
Group([
|
178
|
+
Polyline(ps, colour, 1),
|
179
|
+
Polymarkers(ps, repeat(length(ps), Circle(0, 0, markerRadius, colour)))
|
180
|
+
]);
|
181
|
+
|
182
|
+
def lines:
|
183
|
+
zipWith(curry(plot), iterate(nCat, (+)(1), 0), colours)
|
184
|
+
def x_finish: last(xs)
|
185
|
+
def y_finish:
|
186
|
+
maximum(flip(map, data, (lambda (_, kvs): maximum(map(snd, kvs)))));
|
187
|
+
|
188
|
+
match withAxes:
|
189
|
+
case True:
|
190
|
+
def (x_axis, x_finish):
|
191
|
+
axis(Horiz, 0, x_start, x_finish)
|
192
|
+
def (y_axis, y_finish'):
|
193
|
+
axis(Vert, x_start, 0, y_finish);
|
194
|
+
|
195
|
+
viewport(x_start, x_finish, y_finish', defaultMargin, x_axis :| y_axis :| lines)
|
196
|
+
case False:
|
197
|
+
viewport(x_start, x_finish, y_finish, 0, lines);
|
198
|
+
|
199
|
+
def categoricalChart(plotValue, withAxes, colours, sep, data):
|
200
|
+
def gs:
|
201
|
+
stackRight(sep, plotValue(colours, map(snd, data)))
|
202
|
+
def w: length(gs)
|
203
|
+
def h:
|
204
|
+
maximum(map(height, gs));
|
205
|
+
|
206
|
+
match withAxes:
|
207
|
+
case True:
|
208
|
+
def x_axis:
|
209
|
+
catAxis(Horiz, 0, map(fst, data))
|
210
|
+
def (y_axis, h'): axis(Vert, 0, 0, h);
|
211
|
+
|
212
|
+
viewport(0, w, h', defaultMargin, concat2(gs, [x_axis, y_axis]))
|
213
|
+
case False:
|
214
|
+
viewport(0, w, h, 0, gs);
|
215
|
+
|
216
|
+
def rects(colours, ns):
|
217
|
+
zipWith((lambda colour, n: Rect(0, 0, 1, n, colour)), colours, ns);
|
218
|
+
|
219
|
+
def stackedBar(colours, ns):
|
220
|
+
def heights: map(snd, ns)
|
221
|
+
def subtotals:
|
222
|
+
scanl1((+), 0, heights)
|
223
|
+
def dims:
|
224
|
+
zip(0 :| subtotals, heights)
|
225
|
+
def rects:
|
226
|
+
map((lambda ((y, height), colour): Rect(0, y, 1, height, colour)), zip(dims, colours));
|
227
|
+
|
228
|
+
Viewport(0, 0, 1, last(subtotals), "none", 0, Scale(1, 1), Translate(0, 0), Group(rects));
|
229
|
+
|
230
|
+
def barChart:
|
231
|
+
categoricalChart(rects);
|
232
|
+
|
233
|
+
def groupedBarChart:
|
234
|
+
categoricalChart(compose(map, flip(barChart(False), 0)));
|
235
|
+
|
236
|
+
def stackedBarChart:
|
237
|
+
categoricalChart(compose(map, stackedBar));
|
238
|
+
|
239
|
+
def caption(str, Viewport(x, y, w, h, fill, margin, scale, translate, g)):
|
240
|
+
def g':
|
241
|
+
Group([
|
242
|
+
String(x + w / 2, -2, str, "middle", "hanging"),
|
243
|
+
Viewport(0, 0, w, h, fill, margin, scale, translate, g)
|
244
|
+
]);
|
245
|
+
|
246
|
+
Viewport(x, y, w, h, backgroundColour, defaultMargin / 2 + 4, Scale(1, 1), Translate(0, 0), g');
|
@@ -1,41 +1,44 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
1
|
+
def zero(m, n, image):
|
2
|
+
def (m_max, n_max): dims(image);
|
3
|
+
|
4
|
+
if m >= 1 |and| m <= m_max |and| n >= 1 |and| n <= n_max: image ! (m, n)
|
5
|
+
else: 0;
|
6
|
+
|
7
|
+
def wrap(m, n, image):
|
8
|
+
def (m_max, n_max): dims(image);
|
9
|
+
|
10
|
+
image ! (m - 1 |mod| m_max + 1, n - 1 |mod| n_max + 1);
|
11
|
+
|
12
|
+
def extend(m, n, image):
|
13
|
+
def (m_max, n_max): dims(image)
|
14
|
+
def m':
|
15
|
+
min(max(m, 1), m_max)
|
16
|
+
def n':
|
17
|
+
min(max(n, 1), n_max);
|
18
|
+
|
19
|
+
image ! (m', n');
|
20
|
+
|
21
|
+
def matrixSum(matr):
|
22
|
+
def (m, n): dims(matr);
|
23
|
+
|
24
|
+
foldl((+), 0, [matr ! (i, j) for (i, j) in range((1, 1), (m, n))]);
|
25
|
+
|
26
|
+
def convolve(image, kernel, lookup):
|
27
|
+
def ((m, n), (i, j)):
|
28
|
+
(dims(image), dims(kernel))
|
29
|
+
def (half_i, half_j):
|
30
|
+
(i |quot| 2, j |quot| 2)
|
31
|
+
def area: i * j;
|
32
|
+
def interMatrix(m', n'):
|
33
|
+
@doc("""Intermediate matrix for element ( ${m'} , ${n'} )""")
|
34
|
+
[| @doc("""Multiply these two elements""") lookup(((m' + i') - 1) - half_i, ((n' + j') - 1) - half_j, image) * kernel ! (i', j') for (i', j') in (i, j) |];
|
35
|
+
|
36
|
+
[| matrixSum(interMatrix(m', n')) |quot| area for (m', n') in (m, n) |];
|
37
|
+
|
38
|
+
def matMul(a, b):
|
39
|
+
def ((m, n), (i, j)): (dims(a), dims(b));
|
40
|
+
|
41
|
+
if not(n == i):
|
42
|
+
error("Dimensions don't line up")
|
43
|
+
else:
|
44
|
+
@doc("""Intermediate matrix""") [| sum([a ! (i', k) * b ! (k, j') for k in enumFromTo(1, n)]) for (i', j') in (m, j) |];
|