How to Simulate Phage DNA Injection in Matter.js
This guide demonstrates how to build a 2D biophysical simulation of bacteriophage DNA injection through a bacterial cell envelope using the Matter.js physics engine. You will learn how to construct a segmented cell wall with an entry pore, build the phage capsid and tail structure, assemble flexible DNA polymers using chained rigid bodies and constraints, and apply mechanical forces to drive the genetic material across the membrane.
1. Setting Up the Matter.js Environment
Initialize the core Matter.js modules: Engine,
Render, Runner, Bodies,
Composite, Constraint, and Body.
Configure custom collision categories to control how the DNA interacts
with the phage sheath and the bacterial cell wall without causing
erratic clipping.
const { Engine, Render, Runner, Bodies, Composite, Constraint, Body, Vector } = Matter;
const engine = Engine.create();
const world = engine.world;
engine.gravity.y = 0; // Microscopic scales are dominated by viscous drag rather than gravity
// Define collision categories
const CATEGORY_WALL = 0x0001;
const CATEGORY_PHAGE = 0x0002;
const CATEGORY_DNA = 0x0004;2. Constructing the Bacterial Cell Envelope
A bacterial envelope consists of an outer barrier that must resist penetration. Simulate this by placing two static rectangular bodies side-by-side, leaving a narrow channel (pore) in the center that corresponds to the width of the phage tail tube.
const wallThickness = 20;
const poreWidth = 14;
const wallY = 400;
const leftWall = Bodies.rectangle(150, wallY, 280, wallThickness, {
isStatic: true,
collisionFilter: { category: CATEGORY_WALL }
});
const rightWall = Bodies.rectangle(450, wallY, 280, wallThickness, {
isStatic: true,
collisionFilter: { category: CATEGORY_WALL }
});
Composite.add(world, [leftWall, rightWall]);3. Modeling the Bacteriophage Structure
The bacteriophage consists of an icosahedral capsid (storage head) and a hollow cylindrical tail (sheath/needle) docked at the membrane pore. Model the capsid using static perimeter boundaries to contain the packaged DNA, and extend two parallel guide rails downward to form the injection needle.
const needleLeft = Bodies.rectangle(295, 350, 4, 80, {
isStatic: true,
collisionFilter: { category: CATEGORY_PHAGE }
});
const needleRight = Bodies.rectangle(305, 350, 4, 80, {
isStatic: true,
collisionFilter: { category: CATEGORY_PHAGE }
});
// Capsid container walls
const capsidTop = Bodies.rectangle(300, 220, 100, 10, { isStatic: true });
const capsidLeft = Bodies.rectangle(245, 270, 10, 110, { isStatic: true });
const capsidRight = Bodies.rectangle(355, 270, 10, 110, { isStatic: true });
Composite.add(world, [needleLeft, needleRight, capsidTop, capsidLeft, capsidRight]);4. Assembling DNA as a Polymer Chain
DNA can be approximated as a bead-spring polymer chain. Create an array of small, circular rigid bodies interconnected sequentially with stiff distance constraints. Pack these beads inside the capsid space.
const dnaBeads = [];
const dnaConstraints = [];
const numBeads = 35;
const beadRadius = 4;
for (let i = 0; i < numBeads; i++) {
// Stagger initial bead positions inside the capsid
const x = 280 + (i % 5) * 10;
const y = 240 + Math.floor(i / 5) * 12;
const bead = Bodies.circle(x, y, beadRadius, {
density: 0.001,
frictionAir: 0.05, // Represents cytoplasmic/fluid drag
collisionFilter: {
category: CATEGORY_DNA,
mask: CATEGORY_WALL | CATEGORY_PHAGE | CATEGORY_DNA
}
});
dnaBeads.push(bead);
if (i > 0) {
const link = Constraint.create({
bodyA: dnaBeads[i - 1],
bodyB: bead,
stiffness: 0.9,
damping: 0.1,
length: beadRadius * 2 + 1
});
dnaConstraints.push(link);
}
}
Composite.add(world, [...dnaBeads, ...dnaConstraints]);5. Driving the Injection Process
In nature, DNA injection is driven by high internal capsid pressure and conformational changes in the phage sheath. In Matter.js, replicate this mechanism using one of two methods:
- Active Forward Force: Apply a constant directional force to the lead bead until it clears the pore.
- Capsid Pressure Simulation: Apply radial outward repulsion forces to trailing beads inside the head, pushing them toward the only exit route: the tail tube.
Matter.Events.on(engine, 'beforeUpdate', () => {
const leadBead = dnaBeads[0];
// Apply injection thrust to beads currently inside the needle channel
dnaBeads.forEach((bead) => {
if (bead.position.y < wallY && bead.position.y > 280) {
Body.applyForce(bead, bead.position, { x: 0, y: 0.0005 });
}
});
// Provide an initial guiding push to the lead bead
if (leadBead.position.y < wallY + 50) {
Body.applyForce(leadBead, leadBead.position, { x: 0, y: 0.001 });
}
});6. Execution and Tuning
Run the simulation with Runner.run(runner, engine). Tune
the stiffness of the polymer constraints and increase
engine.positionIterations and
engine.velocityIterations to at least 10 to
prevent the polymer links from stretching or tunneling through the cell
wall during high-pressure translocation.