Public
Edited
Jan 4, 2024
1 fork
Insert cell
Insert cell
// Slider for Number of Generations
viewof generations = Inputs.range([1, 100], {value: 50, step: 1, label: "Generations"})
Insert cell
// Slider for Initial Frequency of Phenotype A
viewof initialP = Inputs.range([0, 1], {value: 0.5, step: 0.01, label: "Initial Frequency of Phenotype A"})
Insert cell
// Cell for Running Simulation and Visualizing Results
chart ={
const data = simulateSelection(initialP, generations);
const svg = d3.select(DOM.svg(width, height));

// Add X and Y axes
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

// Add line for Phenotype A frequency
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", lineGenerator);

console.log(data);
return svg.node();
}
Insert cell
// Setup for the Chart
width = 800
Insert cell
height = 600
Insert cell
margin = [{top: 20, right: 30, bottom: 30, left: 40}]
Insert cell
xScale = d3.scaleLinear().domain([0, generations]).range([margin[0].left, width - margin[0].right])
Insert cell
yScale = d3.scaleLinear().domain([0, 1]).range([height - margin[0].bottom, margin[0].top])
Insert cell
xAxis = g => g.attr("transform", `translate(0,${height - margin[0].bottom})`).call(d3.axisBottom(xScale))
Insert cell
yAxis = g => g.attr("transform", `translate(${margin[0].left},0)`).call(d3.axisLeft(yScale))
Insert cell
lineGenerator = d3.line().x(d => xScale(d.generation)).y(d => yScale(d.frequency))
Insert cell
Insert cell
// Simulation Function
function simulateSelection(initialP, generations) {
let p = initialP;
const frequencies = [p];
for (let i = 0; i < generations; i++) {
const fitnessA = calculateFitness(p);
const fitnessB = calculateFitness(1 - p);
p = updateFrequencies(p, fitnessA, fitnessB);
frequencies.push(p);
}
return frequencies.map((freq, generation) => ({generation, frequency: freq}));
}
Insert cell
// Function to Update Frequencies
function updateFrequencies(p, fitnessA, fitnessB) {
const totalFitness = fitnessA * p + fitnessB * (1 - p);
return (fitnessA * p) / totalFitness;
}
Insert cell
// Function to Calculate Fitness
function calculateFitness(p) {
return 1 - p;
}

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more