{"spec_id":"residual-plot","library":"muix","language":"javascript","code":"// anyplot.ai\n// residual-plot: Residual Plot\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 87/100 | Created: 2026-09-05\nimport { ScatterChart } from \"@mui/x-charts/ScatterChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic LCG) ------------------------------------\n// A simple linear regression predicting house price from square footage, with\n// noise that widens for larger homes — a classic heteroscedastic pattern a\n// residual plot is designed to surface.\nlet seed = 42;\nfunction nextRandom() {\n  seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n  return seed / 0x7fffffff;\n}\nfunction gaussian() {\n  const u1 = Math.max(nextRandom(), 1e-9);\n  const u2 = nextRandom();\n  return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n}\n\nconst HOME_COUNT = 220;\nconst squareFootage = Array.from(\n  { length: HOME_COUNT },\n  () => 600 + nextRandom() * 2900,\n);\nconst housePrices = squareFootage.map((sqft) => {\n  const noise = gaussian() * (8000 + sqft * 18);\n  return 42000 + sqft * 118 + noise;\n});\n\n// Ordinary least squares fit: price = intercept + slope * sqft\nconst meanSqft = squareFootage.reduce((sum, v) => sum + v, 0) / HOME_COUNT;\nconst meanPrice = housePrices.reduce((sum, v) => sum + v, 0) / HOME_COUNT;\nlet covariance = 0;\nlet variance = 0;\nfor (let i = 0; i < HOME_COUNT; i++) {\n  covariance += (squareFootage[i] - meanSqft) * (housePrices[i] - meanPrice);\n  variance += (squareFootage[i] - meanSqft) ** 2;\n}\nconst slope = covariance / variance;\nconst intercept = meanPrice - slope * meanSqft;\n\nconst fittedValues = squareFootage.map((sqft) => intercept + slope * sqft);\nconst residuals = housePrices.map((price, i) => price - fittedValues[i]);\n\nconst residualMean = residuals.reduce((sum, r) => sum + r, 0) / HOME_COUNT;\nconst residualStd = Math.sqrt(\n  residuals.reduce((sum, r) => sum + (r - residualMean) ** 2, 0) /\n    (HOME_COUNT - 1),\n);\nconst upperBand = 2 * residualStd;\nconst lowerBand = -2 * residualStd;\n\n// Points beyond ±2 standard deviations get a semantic-red accent — they are\n// the leverage points / outliers a reviewer checks first.\nconst withinBand = [];\nconst outliers = [];\nfittedValues.forEach((fitted, i) => {\n  const residual = residuals[i];\n  const point = { x: fitted, y: residual, id: i };\n  if (residual > upperBand || residual < lowerBand) {\n    outliers.push(point);\n  } else {\n    withinBand.push(point);\n  }\n});\n\nconst TITLE_HEIGHT = 66;\n\n// --- Chart (default-exported component — the harness mounts it) ------------\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n\n  return (\n    <Box\n      sx={{\n        width,\n        height,\n        display: \"flex\",\n        flexDirection: \"column\",\n        paddingTop: \"20px\",\n      }}\n    >\n      <Typography\n        sx={{\n          color: t.ink,\n          fontSize: 26,\n          fontWeight: 600,\n          textAlign: \"center\",\n          lineHeight: 1.2,\n        }}\n      >\n        residual-plot · javascript · muix · anyplot.ai\n      </Typography>\n      <ScatterChart\n        width={width}\n        height={height - TITLE_HEIGHT}\n        skipAnimation\n        series={[\n          {\n            id: \"residuals\",\n            data: withinBand,\n            label: \"Residuals\",\n            markerSize: 7,\n            color: \"rgba(0, 158, 115, 0.55)\",\n          },\n          {\n            id: \"outliers\",\n            data: outliers,\n            label: \"Outliers (|residual| > 2σ)\",\n            markerSize: 11,\n            color: \"rgba(174, 48, 48, 0.85)\",\n          },\n        ]}\n        xAxis={[\n          {\n            label: \"Fitted Price ($)\",\n            labelStyle: { fontSize: 16, fill: t.ink },\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n          },\n        ]}\n        yAxis={[\n          {\n            label: \"Residual ($)\",\n            labelStyle: { fontSize: 16, fill: t.ink },\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n          },\n        ]}\n        margin={{ left: 110, right: 40, top: 20, bottom: 90 }}\n        grid={{ horizontal: true, vertical: true }}\n        slotProps={{\n          legend: {\n            position: { vertical: \"top\", horizontal: \"middle\" },\n            direction: \"row\",\n            labelStyle: { fontSize: 13, fill: t.inkSoft },\n          },\n        }}\n        sx={{\n          \"& .MuiChartsGrid-line\": { stroke: t.grid, strokeWidth: 1 },\n          \"& circle\": { stroke: t.pageBg, strokeWidth: 1 },\n        }}\n      >\n        <ChartsReferenceLine\n          y={0}\n          label=\"Perfect fit: residual = 0\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.ink, strokeWidth: 2.5 }}\n          labelStyle={{ fill: t.ink, fontSize: 14, fontWeight: 600 }}\n        />\n        <ChartsReferenceLine\n          y={upperBand}\n          label={`+2σ: ${Math.round(upperBand).toLocaleString()}`}\n          labelAlign=\"end\"\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"8 6\",\n            strokeWidth: 1.75,\n          }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 14 }}\n        />\n        <ChartsReferenceLine\n          y={lowerBand}\n          label={`−2σ: ${Math.round(lowerBand).toLocaleString()}`}\n          labelAlign=\"end\"\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"8 6\",\n            strokeWidth: 1.75,\n          }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 14 }}\n        />\n      </ScatterChart>\n    </Box>\n  );\n}\n"}