The Introspection Trap
About This Sketch
Seven wave strands emerge clear and coherent on the left — a clean first judgment — then progressively fragment into noise as "analysis" accumulates rightward. The more you examine, the more the original signal degrades into scattered rationalization. Visualizing the verbal overshadowing effect: introspection replaces signal with story.
Algorithm
Signal degradation through analysis — seven parallel wave strands travel left
to right. On the far left, a glowing dot represents an unexamined first judgment:
clean and coherent. As position moves rightward, each wave strand becomes
progressively noisier and more fragmented, with stray scatter dots appearing
to represent rationalization fragments. Color shifts from warm amber (clear
judgment) to muted taupe (analyzed noise).
This sketch accompanies the blog post "The Introspection Trap" and visualizes
how carefully examining your reasons for a decision degrades rather than
clarifies the underlying signal.
Pseudocode
SETUP:
Initialize canvas (400x300)
Generate random noise seeds for each of 7 wave strands
DRAW (every frame):
Get current theme colors
Clear background
Increment time
FOR each column (0 to 79) across the canvas:
Compute analysisFrac (0=left/pure, 1=right/degraded)
FOR each of 7 wave strands:
Compute clean sine wave position
Blend in Perlin noise proportional to analysisFrac squared
Shift color from accent2 (warm) to accent3 (muted)
Reduce alpha and dot size rightward
Scatter fragment dots stochastically for high analysisFrac columns
Draw pulsing clarity dot at far left (original judgment)
Draw labels: "first judgment" left, "after analysis" right
Draw arrow and caption
Source Code
let sketch = function(p) {
let time = 0;
let noiseSeeds = [];
const WAVE_COUNT = 7;
const COLS = 80;
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
for (let i = 0; i < WAVE_COUNT; i++) {
noiseSeeds.push(p.random(1000));
}
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time += 0.012;
for (let col = 0; col < COLS; col++) {
let x = p.map(col, 0, COLS - 1, 30, 370);
let analysisFrac = p.map(col, 0, COLS - 1, 0, 1);
for (let w = 0; w < WAVE_COUNT; w++) {
let baseY = p.map(w, 0, WAVE_COUNT - 1, 60, 240);
let amplitude = p.map(analysisFrac, 0, 1, 22, 6);
let cleanY = baseY + amplitude * Math.sin(time * (1 + w * 0.18) + w * 0.9);
let noiseAmt = p.map(analysisFrac, 0, 1, 0, 1);
let n = p.noise(noiseSeeds[w] + col * 0.12, time * 0.6 + w * 0.4);
let noiseY = p.map(n, 0, 1, -28, 28);
let y = p.lerp(cleanY, cleanY + noiseY, noiseAmt * noiseAmt);
let waveAlpha = p.map(Math.abs(w - (WAVE_COUNT - 1) / 2), 0, (WAVE_COUNT - 1) / 2, 1, 0.25);
let r = p.lerp(colors.accent2[0], colors.accent3[0], analysisFrac);
let g = p.lerp(colors.accent2[1], colors.accent3[1], analysisFrac);
let b = p.lerp(colors.accent2[2], colors.accent3[2], analysisFrac);
let a = p.lerp(170, 60, analysisFrac * analysisFrac) * waveAlpha;
p.noStroke();
p.fill(r, g, b, a);
let dotSize = p.lerp(3.2, 1.4, analysisFrac);
p.circle(x, y, dotSize);
if (analysisFrac > 0.55 && p.random() < analysisFrac * 0.18) {
let fragX = x + p.random(-9, 9);
let fragY = y + p.random(-18, 18);
p.fill(r, g, b, a * 0.4);
p.circle(fragX, fragY, dotSize * 0.7);
}
}
}
let dotPulse = 0.82 + 0.18 * Math.sin(time * 2.3);
p.noStroke();
p.fill(...colors.accent1, 30 * dotPulse);
p.circle(30, 150, 28 * dotPulse);
p.fill(...colors.accent2, 180 * dotPulse);
p.circle(30, 150, 7 * dotPulse);
p.noStroke();
p.fill(...colors.accent3, 55);
p.textSize(8.5);
p.textAlign(p.CENTER);
p.text('first judgment', 30, 288);
p.text('after analysis', 370, 288);
p.stroke(...colors.accent3, 38);
p.strokeWeight(0.8);
p.line(65, 282, 340, 282);
p.noStroke();
p.fill(...colors.accent3, 38);
p.triangle(345, 282, 337, 278, 337, 286);
p.noStroke();
p.fill(...colors.accent3, 60);
p.textAlign(p.CENTER);
p.textSize(9);
p.text('examining your reasons degrades the signal', 200, 18);
};
};