chart = {
const width = 928;
const height = width;
const drugColor = d3.scaleOrdinal()
.domain(antibiotics.map((d) => d.drug))
.range(["rgb(10, 50, 100)", "rgb(200, 70, 50)", "black"]);
const gramColor = d3.scaleOrdinal()
.domain(antibiotics.map((d) => d.gram))
.range(["rgba(230, 130, 110, .8)", "rgba(174, 174, 184, .8)"]);
const innerRadius = 90;
const outerRadius = 340;
const min = Math.sqrt(Math.log(.001 * 1e4));
const max = Math.sqrt(Math.log(1000 * 1e4));
const a = (outerRadius - innerRadius) / (min - max);
const b = innerRadius - a * max;
const radius = (mic) => a * Math.sqrt(Math.log(mic * 1e4)) + b;
const nameAngle = d3.scaleBand()
.domain(antibiotics.map((d) => d.bacteria))
.range([0, 2 * Math.PI])
.paddingOuter(0.5);
const drugAngle = d3.scaleBand()
.domain(antibiotics.map((d) => d.drug))
.range([0, nameAngle.bandwidth()])
.padding(0.5);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width / 2, 60 - height / 2, width, height])
.attr("font-family", "sans-serif")
.attr("font-size", "10")
.attr("style", "max-width: 100%; height: auto; background: rgb(240, 225, 210);");
svg.append("g")
.selectAll()
.data(nameAngle.domain())
.join("path")
.attr("d", d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle((d) => nameAngle(d))
.endAngle((d) => nameAngle(d) + nameAngle.bandwidth()))
.attr("fill", (d) => gramColor(antibiotics.find((b) => b.bacteria === d).gram));
svg.append("g")
.selectAll()
.data(antibiotics)
.join("path")
.attr("d", d3.arc()
.innerRadius(innerRadius)
.outerRadius((d) => radius(d.mic))
.startAngle((d) => nameAngle(d.bacteria) + drugAngle(d.drug))
.endAngle((d) => nameAngle(d.bacteria) + drugAngle(d.drug) + drugAngle.bandwidth()))
.attr("fill", (d) => drugColor(d.drug));
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#eee")
.selectAll()
.data(d3.range(-3, 4))
.join("circle")
.attr("r", (i) => radius(Math.pow(10, i)));
svg.append("g")
.selectAll()
.data(d3.range(-3, 3))
.join("text")
.attr("y", (i) => -radius(Math.pow(10, i)))
.attr("dy", "0.32em")
.attr("text-anchor", "middle")
.text((i) => Math.pow(10, i).toFixed((i > 0) ? 0 : -i));
svg.append("g")
.attr("fill", "none")
.attr("stroke", "black")
.selectAll()
.data([nameAngle.domain()[0]].concat(nameAngle.domain()))
.join("path")
.attr("d", d3.arc()
.innerRadius(innerRadius - 10)
.outerRadius(outerRadius + 10)
.startAngle((d, i) => nameAngle(d) + (i ? nameAngle.bandwidth() : 0))
.endAngle((d, i) => nameAngle(d) + (i ? nameAngle.bandwidth() : 0)));
svg.append("g")
.selectAll()
.data(nameAngle.domain())
.join("text")
.attr("text-anchor", "middle")
.attr("dy", "0.32em")
.attr("transform", (d) => {
const r = outerRadius + 10;
const a = nameAngle(d) + nameAngle.bandwidth() / 2;
return `
translate(${d3.pointRadial(a, r)})
rotate(${a * 180 / Math.PI + (a > Math.PI ? 90 : -90)})
`;
})
.text((d) => d);
svg.append("g")
.style("text-transform", "capitalize")
.selectAll()
.data(drugColor.domain())
.join("g")
.attr("transform", (d, i) => `translate(0,${i * 18 - 22})`)
.call((g) => g.append("rect")
.attr("x", -39)
.attr("y", -6)
.attr("width", 36)
.attr("height", 12)
.attr("fill", drugColor))
.call((g) => g.append("text")
.attr("x", 6)
.attr("dy", "0.32em")
.text((d) => d));
svg.append("g")
.attr("transform", `translate(0,${outerRadius + 120})`)
.selectAll()
.data(gramColor.domain())
.join("g")
.attr("transform", (d, i) => `translate(0,${i * 18})`)
.call((g) => g.append("circle")
.attr("cx", -12)
.attr("r", 6)
.attr("fill", gramColor))
.call((g) => g.append("text")
.attr("x", 6)
.attr("dy", "0.32em")
.text((d) => `Gram-${d}`));
return svg.node();
}