unfortunately I'm not able to find my mistake, so i'm asking you in the hope that someone can help me. What I want to have in the end is, that only every fifth bin is labeled, if the binNumber is higher than 30. I tried every inline condition I know, but non of this worked so far.
What I currently have is the following:
const binWidth = d3.max(testData, (d) => d.expressionValue) / (binNumber - 1);
const bins = Array.from({ length: binNumber}, () => ({
x0: 0,
x1: 0,
length: 0, // gets updated later on
}));
bins.forEach((bin, i) => {
bin.x0 = (i === 0) ? 0 : bins[i - 1].x1;
bin.x1 = bin.x0 + binWidth;
});
testData.forEach((d) => {
for (let i = 0; i < binNumber; i++) {
const bin = bins[i];
if (d.expressionValue >= bin.x0 && d.expressionValue < bin.x1) {
bin.length += 1;
if(this.proteinId != null && d.proteinId == this.proteinId){
binIndexOfInputProteinId = i; // bin at position i needs to be in a different color
}
break;
}
}
});
const x = d3.scaleLinear()
.domain([0, d3.max(testData, (d) => d.expressionValue) + binWidth])
.range([marginLeft, width - marginRight]);
const y = d3.scaleLinear()
.domain([0, d3.max(bins, (d) => d.length)])
.range([height - marginBottom, marginTop + 15]);
const svg = d3.select(this.$refs.barContainer)
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height + 20])
.attr("style", "max-width: 100%; height: auto;");
const binMidpoints = bins.map((bin) => (bin.x0 + bin.x1) / 2);
svg.append("g")
.selectAll()
.data(bins)
.join("rect")
.attr("x", (d) => x(d.x0) + 1)
.attr("width", (d) => x(d.x1) - x(d.x0) -1)
.attr("y", (d) => y(Math.max(d.length, 0.05)))
.attr("height", (d) => Math.max(y(0) - y(d.length), minRectHeight))
.attr("fill", (d, i) => (i == binIndexOfInputProteinId && binIndexOfInputProteinId != null) ? "red" : "steelblue");
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(d3.axisBottom(x)
.tickValues([
...((this.binNumber < 10) ? binMidpoints : []),
...((this.binNumber <= 20) ? bins.map((bin, i) => (bin.x1)) : []),
...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1 : null)) : [])
])
.tickSizeOuter(0)
.tickFormat((d) => d.toFixed(1)))
.call((g) => g.append("text")
.attr("x", width)
.attr("y", marginBottom + 15)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text("Protein expression value →"))
.selectAll("text")
.attr("style", `font-size: 18px`);
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(d3.axisLeft(y).ticks(10))
.call((g) => g.append("text")
.attr("x", marginLeft - 180)
.attr("y", marginTop)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text("↑ Frequency of proteins with corresponding expression"))
.selectAll("text")
.attr("style", `font-size: 18px`);
return svg.node();
The important part is the following:
.tickValues([
...((this.binNumber < 10) ? binMidpoints : []),
...((this.binNumber <= 30) ? bins.map((bin, i) => (bin.x1)) : []),
...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1 : null)) : [])
])
The first two conditions work well. The problem is the last one. If I have found this out correctly, then this does not work because of the "null". However, I have also tried "undefined" and an empty string, but unfortunately that doesn't work either. In my histogram there are simply no more axes to be seen.
Then I tried a different inline condition, because I thought maybe I must not do anything in the else statement:
...((this.binNumber > 20) && bins.map((bin, i) => (i % 5 === 0 ? bin.x1)))
There the error occurs that the ":" is missing.
...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1)) : [])
Didn"t worked as well.
Can you please help me how I can solve this? Thank you very much :D