{"spec_id":"spectrum-basic","library":"echarts","language":"javascript","code":"// anyplot.ai\n// spectrum-basic: Frequency Spectrum Plot\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 89/100 | Created: 2026-09-09\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Synthetic vibration signal: three characteristic machinery frequencies\n// (running speed 60 Hz, gear mesh 240 Hz, bearing fault 850 Hz) plus a\n// 1/f-shaped noise floor, expressed as a power spectrum in dB.\nconst SAMPLE_RATE = 4096;\nconst NUM_BINS = 1024;\nconst PEAKS = [\n  { freq: 60, amplitude: 1.0, width: 3, role: \"running speed\" },\n  { freq: 240, amplitude: 0.55, width: 5, role: \"gear mesh\" },\n  { freq: 850, amplitude: 0.32, width: 9, role: \"bearing fault\" },\n];\n\n// Tiny fixed-seed LCG for reproducible pseudo-noise.\nlet lcgState = 42;\nfunction nextRandom() {\n  lcgState = (lcgState * 1103515245 + 12345) % 2147483648;\n  return lcgState / 2147483648;\n}\n\nconst frequencies = [];\nconst amplitudesDb = [];\nfor (let i = 1; i < NUM_BINS; i += 1) {\n  const freq = (i / NUM_BINS) * (SAMPLE_RATE / 2);\n  let magnitude = 0.02 + 0.6 / freq; // 1/f-shaped noise floor\n  for (const peak of PEAKS) {\n    const distance = (freq - peak.freq) / peak.width;\n    magnitude += peak.amplitude * Math.exp(-distance * distance);\n  }\n  magnitude *= 1 + (nextRandom() - 0.5) * 0.08; // small measurement jitter\n  frequencies.push(Math.round(freq * 10) / 10);\n  amplitudesDb.push(Math.round(20 * Math.log10(magnitude) * 10) / 10);\n}\n\nconst dominantIndices = PEAKS.map((peak) => {\n  let closest = 0;\n  let closestDist = Infinity;\n  frequencies.forEach((f, idx) => {\n    const dist = Math.abs(f - peak.freq);\n    if (dist < closestDist) {\n      closestDist = dist;\n      closest = idx;\n    }\n  });\n  return closest;\n});\n\n// --- Init --------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option --------------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"Machinery Vibration Spectrum · spectrum-basic · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    top: 18,\n    textStyle: { color: t.ink, fontSize: 18, fontWeight: 500 },\n  },\n  legend: {\n    data: [\"Power spectrum\", \"Dominant frequencies\"],\n    top: 54,\n    textStyle: { color: t.ink, fontSize: 14 },\n  },\n  grid: { left: 90, right: 60, top: 130, bottom: 90 },\n  xAxis: {\n    type: \"log\",\n    name: \"Frequency (Hz)\",\n    nameLocation: \"middle\",\n    nameGap: 45,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    min: 4,\n    max: 2048,\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: true, lineStyle: { color: t.grid } },\n  },\n  yAxis: {\n    type: \"value\",\n    name: \"Power (dB)\",\n    nameLocation: \"middle\",\n    nameGap: 60,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [\n    {\n      type: \"line\",\n      name: \"Power spectrum\",\n      data: frequencies.map((f, idx) => [f, amplitudesDb[idx]]),\n      showSymbol: false,\n      lineStyle: { color: t.palette[0], width: 2 },\n      areaStyle: { color: t.palette[0], opacity: 0.15, origin: \"start\" },\n    },\n    {\n      type: \"scatter\",\n      name: \"Dominant frequencies\",\n      data: dominantIndices.map((idx, i) => ({\n        value: [frequencies[idx], amplitudesDb[idx]],\n        name: `${PEAKS[i].freq} Hz — ${PEAKS[i].role}`,\n      })),\n      symbolSize: 14,\n      itemStyle: {\n        color: \"transparent\",\n        borderColor: t.palette[1],\n        borderWidth: 2.5,\n      },\n      label: {\n        show: true,\n        position: \"top\",\n        distance: 8,\n        formatter: (params) => params.name,\n        color: t.ink,\n        fontSize: 12,\n        fontWeight: 500,\n      },\n    },\n  ],\n});\n\nchart.on(\"finished\", () => {\n  window.__anyplotReady = true;\n});\n"}