Simulating Motor Protein Transport in Matter.js
This article explains how to simulate biological motor protein cargo transport along microtubule filaments using the Matter.js 2D physics engine. You will learn how to represent biological components—such as microtubules, motor heads (like kinesin), and vesicle cargo—as rigid bodies and constraints, while applying low Reynolds number dynamics, Brownian thermal noise, and step-wise propulsion to realistically mimic intracellular transport.
1. Conceptual Mapping to Matter.js
To model intracellular transport, biological structures must be mapped to 2D rigid body mechanics:
- Microtubule Track: A static linear body
(
isStatic: true) or a fixed vector pathway defining the direction of movement. - Motor Protein: A small dynamic body or kinematic anchor that traverses along the track vector in discrete steps.
- Cargo (Vesicle): A larger circular body
(
Bodies.circle) with mass and high friction to mimic movement through viscous cytoplasm. - Tether (Coiled-coil stalk): A spring-like
constraint (
Matter.Constraint) connecting the motor body to the cargo.
2. Setting Up the Environment
Intracellular environments operate at very low Reynolds numbers,
meaning viscous drag dominates over inertia. Set the world's standard
gravity to zero and apply high frictionAir to the cargo to
simulate the viscosity of the cytosol.
const { Engine, Render, Runner, Bodies, Composite, Constraint, Body, Vector } = Matter;
const engine = Engine.create({
gravity: { x: 0, y: 0, scale: 0 }
});3. Creating Track, Motor, and Cargo Bodies
Define the static microtubule track, the stepping motor unit, and the suspended cargo.
// Microtubule track
const track = Bodies.rectangle(400, 300, 700, 10, {
isStatic: true,
isSensor: true, // Prevents physical collisions with the motor
render: { fillStyle: '#4CAF50' }
});
// Cargo vesicle
const cargo = Bodies.circle(100, 240, 30, {
mass: 5,
frictionAir: 0.15, // High drag to simulate cytosol
render: { fillStyle: '#FF5722' }
});
// Motor head
const motor = Bodies.circle(100, 290, 8, {
mass: 0.5,
frictionAir: 0.2,
render: { fillStyle: '#2196F3' }
});
// Tether between motor and cargo
const tether = Constraint.create({
bodyA: motor,
bodyB: cargo,
stiffness: 0.05,
damping: 0.01,
render: { strokeStyle: '#9E9E9E', lineWidth: 2 }
});
Composite.add(engine.world, [track, cargo, motor, tether]);4. Simulating the Stepping Mechanism
Motor proteins like kinesin move processively along microtubules in
discrete, hand-over-hand steps (typically 8 nm per ATP hydrolyzed). In
Matter.js, this is simulated using an event loop listener
(beforeUpdate) that applies intermittent forward forces or
positional displacements along the track's directional vector.
const stepSize = 4; // Visual step magnitude
const stepInterval = 15; // Engine ticks between steps
let tick = 0;
Matter.Events.on(engine, 'beforeUpdate', () => {
tick++;
// Step-wise forward movement along the track (X-axis)
if (tick % stepInterval === 0 && motor.position.x < 700) {
Body.setPosition(motor, {
x: motor.position.x + stepSize,
y: track.position.y - 10
});
}
// Brownian motion: Apply slight random thermal forces to cargo
const thermalForce = Vector.create(
(Math.random() - 0.5) * 0.002,
(Math.random() - 0.5) * 0.002
);
Body.applyForce(cargo, cargo.position, thermalForce);
});5. Tuning Physical Properties for Realism
- Tether Elasticity: Adjust the
stiffnessandlengthproperties of theConstraint. Lower stiffness creates visual lag, showing the cargo being pulled behind the motor through a viscous medium. - Stall Force: Motor proteins have a stall force limit (around 6–7 pN for kinesin). You can track the extension distance of the tether constraint; if the stretch exceeds a threshold (due to simulated biological obstacles), prevent the motor from stepping forward to simulate motor stalling.
- Processivity and Detachment: Introduce a random probability check per step where the tether or motor is removed from the track to model spontaneous detachment into the cytoplasm.