Public
Edited
Aug 24, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
seeds = [
14, // .29
32, // .33
16, // .36
17, // .40
13, // .43
8, // .497
71, // .508
18, // .57
43, // .60
106, // .64
412, // .67
491 // .71
]
Insert cell
Insert cell
Insert cell
Insert cell
// debias the low-noise data to have the same mean as the high-noise data
function debiasMeans(data) {
return data.map((stimulus) => {
if (stimulus.noise[1] != highNoise) {
const lowNoiseData = stimulus.lineData.map((d) => d.y);
const highNoiseData = stimulus.highNoiseData.map((d) => d.y);
let fix = null;

if (stimulus.flip) {
const factor =
(1 - d3.mean(highNoiseData)) / (1 - d3.mean(lowNoiseData));

fix = (d) => ({
...d,
y: 1 - (1 - d.y) * factor
});
} else {
const factor = d3.mean(highNoiseData) / d3.mean(lowNoiseData);

fix = (d) => ({
...d,
y: d.y * factor
});
}

return {
...stimulus,
data: stimulus.data.map(fix),
lineData: stimulus.lineData.map(fix)
};
} else {
return stimulus;
}
});
}
Insert cell
// apply the scale of the high-noise data to the low-noise data. Almost the same as debiasing the means (but disable scaling in data generation) but not exaclty since noise changes isn't exactly balanced.
function scaleData(data) {
return data.map((stimulus) => {
const highNoiseYs = stimulus.highNoiseData.map((d) => d.y);
const scale = d3.scaleLinear().domain(d3.extent(highNoiseYs));

return {
...stimulus,
data: stimulus.data.map((d) => ({
...d,
y: scale(d.y)
})),
lineData: stimulus.lineData.map((d) => ({
...d,
y: scale(d.y)
}))
};
});
}
Insert cell
function dataGenerator(lowNoise, highNoise, seed, flip, n, scaleData) {
let rand = random(seed);

// https://github.com/d3/d3-random#randomNormal
const randNormal = d3.randomNormal.source(rand)(mu, sigma);

const start = 1;

let value = start;

const motion = fc
.randomGeometricBrownianMotion()
.mu(mu)
.sigma(sigma)
.period(1)
.steps(n + smoothing)
.random(randNormal)(start);

const sequence = movingAverage(motion, smoothing).slice(smoothing);

const scale = d3.scaleLinear().domain(d3.extent(sequence));

const baseSequence = sequence.map(scale);

// reset random to follow implementation in https://observablehq.com/d/2dcf91fdecdd5ff2
rand = random(seed + 1);

let out = d3.range(n).map((i) => {
const base = baseSequence[i];
const noise = lowNoise * (1 - base) + highNoise * base;
return base + (rand() - 0.5) * noise;
});

if (scaleData) {
const scale2 = d3.scaleLinear().domain(d3.extent(out));
out = out.map(scale2);
}

if (flip) {
out = out.map((d) => 1 - d);
}

return out;
}
Insert cell
Insert cell
function makeView(d, w = 500, h = 200, showLine = false) {
return {
title: title(d),
width: w,
height: h,
data: {
values: d.data
},
layer: [
{
mark: d.type === "line" ? "line" : "circle",
encoding: {
x: {
field: "x",
type: "quantitative",
title: "Time",
axis: null,
scale: { nice: false }
},
y: {
field: "y",
type: "quantitative",
scale: { domain: [0, 1] },
title: "Value",
axis: null
}
}
},
{
mark: {
type: "rule",
color: "firebrick"
},
encoding: {
y: {
field: "y",
aggregate: "mean"
}
}
},
...((d.type === "point_arc" || d.type === "point") && showLine
? [
{
data: {
values: d.lineData
},
mark: {
type: "line",
opacity: 0.5,
size: 0.5
},
encoding: {
x: { field: "x", type: "quantitative" },
y: {
field: "y",
type: "quantitative"
}
}
}
]
: [])
]
};
}
Insert cell
Insert cell
function title(d) {
return `Seed: ${d.seed}, Type: ${d.type}, Noise: ${d.noise[0]} to ${d.noise[1]}, Flipped: ${d.flip}, Mean: ${d.mean}, Index: ${d.index}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more