Spaces:
Sleeping
Sleeping
| """Histogram template — fetch-and-adapt from d3-graph-gallery.com. | |
| Adapted from d3-graph-gallery.com (Yan Holtz) — | |
| https://d3-graph-gallery.com/graph/histogram_basic.html | |
| """ | |
| from __future__ import annotations | |
| from pydantic import BaseModel | |
| from app.agents.d3.registry import D3Template, register | |
| class HistogramData(BaseModel): | |
| title: str = "" | |
| x_label: str = "" | |
| values: list[float] | |
| bins: int = 20 | |
| _HTML = """<!-- Adapted from d3-graph-gallery.com (Yan Holtz) — https://d3-graph-gallery.com/graph/histogram_basic.html --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://d3js.org/d3.v7.min.js"></script> | |
| <style> | |
| html, body { margin: 0; padding: 0; width: 100vw; height: 100vh; background: #FAF7F2; color: #1A3557; font-family: Georgia, 'Libre Caslon Text', serif; overflow: hidden; } | |
| #my_dataviz { width: 100vw; height: 100vh; } | |
| .axis text { fill: #1A3557; font-size: 12px; } | |
| .axis path, .axis line { stroke: #1A3557; } | |
| .chart-title { fill: #1A3557; font-size: 18px; text-anchor: middle; } | |
| .axis-label { fill: #1A3557; font-size: 13px; text-anchor: middle; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="my_dataviz"></div> | |
| <script> | |
| const data = __DATA__; | |
| // set the dimensions and margins of the graph | |
| const margin = {top: 50, right: 30, bottom: 60, left: 60}, | |
| width = 960 - margin.left - margin.right, | |
| height = 600 - margin.top - margin.bottom; | |
| // append the svg object to the body of the page | |
| const svg = d3.select("#my_dataviz") | |
| .append("svg") | |
| .attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`) | |
| .attr("preserveAspectRatio", "xMidYMid meet") | |
| .style("width", "100%") | |
| .style("height", "100%") | |
| .append("g") | |
| .attr("transform", `translate(${margin.left},${margin.top})`); | |
| // Chart title | |
| svg.append("text") | |
| .attr("class", "chart-title") | |
| .attr("x", width / 2) | |
| .attr("y", -20) | |
| .text(data.title); | |
| // X axis: scale and draw | |
| const x = d3.scaleLinear() | |
| .domain(d3.extent(data.values)) | |
| .range([0, width]); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .attr("transform", `translate(0, ${height})`) | |
| .call(d3.axisBottom(x)); | |
| svg.append("text") | |
| .attr("class", "axis-label") | |
| .attr("x", width / 2) | |
| .attr("y", height + margin.bottom - 10) | |
| .text(data.x_label); | |
| // set the parameters for the histogram | |
| const histogram = d3.histogram() | |
| .domain(x.domain()) | |
| .thresholds(x.ticks(data.bins)); | |
| // apply this function to the values to get the bins | |
| const bins = histogram(data.values); | |
| // Y axis: scale and draw | |
| const y = d3.scaleLinear() | |
| .range([height, 0]) | |
| .domain([0, d3.max(bins, d => d.length)]); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .call(d3.axisLeft(y)); | |
| // append the bar rectangles to the svg element | |
| svg.selectAll("rect") | |
| .data(bins) | |
| .join("rect") | |
| .attr("x", 1) | |
| .attr("transform", d => `translate(${x(d.x0)}, ${y(d.length)})`) | |
| .attr("width", d => Math.max(0, x(d.x1) - x(d.x0) - 1)) | |
| .attr("height", d => height - y(d.length)) | |
| .style("fill", "#4A7FB5"); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| golden_sample = HistogramData( | |
| title="Demo", | |
| x_label="Value", | |
| values=[2, 4, 4, 6, 7, 7, 7, 8, 9, 12], | |
| bins=8, | |
| ) | |
| register( | |
| D3Template( | |
| id="histogram", | |
| family="chart", | |
| title="Histogram", | |
| when_to_use="Show the distribution of a single numeric variable across many observations.", | |
| data_requirements="A list of numeric values (no pre-binning needed).", | |
| schema=HistogramData, | |
| html_template=_HTML, | |
| golden_sample=golden_sample, | |
| ) | |
| ) | |