Abstract
In October 2024 we published a Python simulation of “brain healing” and a companion post on mirror neurons. The simulation places 2,500 cells on a grid, damages a circular region, and lets healthy neighbours raise a compensation value while damaged cells may recover. The post concluded that stimulation and early intervention help recovery. An audit of the published code finds that the recovery probability adds an age term drawn uniformly from 0 to 1 to three terms that are each a few thousandths. Damaged cells therefore recover about 50% of the time per step regardless of stimulation. In 20 seeded runs, 49% of lesioned cells were active again after one step and 96% after twenty steps, and switching stimulation off changed nothing. Early intervention was never compared with late intervention. With the age term removed, stimulation does raise recovery, but by construction. We restate the model as what it is, a toy of load redistribution among neighbours, correct two statements about the neuroscience it cited, and note what a model would need before it could say anything about rehabilitation. This paper is not medical advice.
Zusammenfassung
Im Oktober 2024 haben wir eine Python-Simulation zur „Heilung des Gehirns“ und einen Begleitbeitrag über Spiegelneuronen veröffentlicht. Die Simulation verteilt 2.500 Zellen auf ein Raster und schädigt einen kreisförmigen Bereich. Gesunde Nachbarzellen erhöhen daraufhin einen Kompensationswert, geschädigte Zellen können sich erholen. Der Beitrag folgerte, dass Stimulation und frühe Intervention die Erholung fördern. Der veröffentlichte Code zeigt etwas anderes. Die Erholungswahrscheinlichkeit addiert zu drei Termen von wenigen Tausendsteln einen Altersterm, der gleichverteilt zwischen 0 und 1 liegt. Geschädigte Zellen erholen sich deshalb in etwa jedem zweiten Schritt, ob stimuliert wird oder nicht. In 20 Läufen mit festen Seeds waren nach einem Schritt 49 % und nach zwanzig Schritten 96 % der geschädigten Zellen wieder aktiv, mit und ohne Stimulation. Frühe und späte Intervention wurden nie miteinander verglichen. Ohne den Altersterm wirkt Stimulation zwar, aber nur, weil die Regel es so vorschreibt. Wir beschreiben das Modell als das, was es ist, nämlich ein Minimalmodell für die Umverteilung von Last zwischen Nachbarzellen. Außerdem korrigieren wir zwei Aussagen zur zitierten Neurowissenschaft und skizzieren, was ein Modell bräuchte, um etwas über Rehabilitation auszusagen. Dieser Beitrag ist keine medizinische Beratung.
1. The bug that cured the brain
Our October 2024 simulation of brain healing worked too well. A frame from the video we published with it shows step 261 of a run in which the grid had taken several lesions. The counter in the corner reads: active 2,498, inactive 2. The line chart below it shows the count of active cells jumping to nearly 2,500 at the start of the run and staying there.
Real brains do not do that, and neither should a model whose purpose is to show slow, partial, effortful recovery. The cause is one line of arithmetic, described in section 3. Before that, section 2 describes what the model is, because the post described something grander. Section 5 corrects the neuroscience, including the companion post on mirror neurons, and section 7 draws the one lesson that transfers to engineering work: if removing the cause does not remove the effect, you have not found a cause.
2. What the model is
The code is a single file of 456 lines, public on GitHub since April 2025. Its state is a set of 50 × 50 arrays:
| Array | Meaning in the post | What it does in the code |
|---|---|---|
neurons | Healthy or damaged neurons | 0 or 1. 80% start at 1. |
function_map | How much work a neuron does | A float. Active cells add a little each step for every inactive neighbour. Above 1.5 the cell's health starts to fall. |
neuron_types | Regular, fast-adapting, slow-adapting | 0, 1 or 2 with probabilities 0.7, 0.15, 0.15. Changes two multipliers. |
health_map | Resistance to damage | Starts between 0.8 and 1.0. |
age_map | Younger neurons adapt faster | Starts uniform between 0 and 100, grows by 0.01 per step. |
stimulation | Physical therapy | Raised in circles, decays by 5% per step. |
connections | “Synaptic connections between neurons” | Grows between active neighbours. No rule ever reads it. It feeds one display panel. |
There are no synapses in any functional sense: no weights through which one cell's activity changes another's, no propagation of activity, no Hebbian or homeostatic learning rule, and no task through which “function” could be measured. Compensation is a counter. An active cell with k inactive neighbours adds 0.005 × k × (type factor) × (age factor) × (1 + stimulation) to its function value per step.
One detail of the damage rule matters for later. A cell inside the lesion is destroyed with probability intensity / (health * resistance). The initial lesion uses intensity 1.0 and health never exceeds 1.0, so for regular and fast cells that probability is at least 1. They always die. Slow cells, with resistance 1.5, die with probability between 0.67 and 0.83. The post said slow cells had “a 50% better chance of surviving”. In fact they are the only cells that can survive at all, and only 17% to 33% of them do.
Read honestly, this is a cellular automaton of load redistribution: when a unit fails, its neighbours take on more work, and units pushed far past capacity wear out. That is a legitimate thing to simulate. It is not a model of cortical plasticity.
3. The recovery bug
Each step, every inactive cell may switch back on. This is the rule, from update() in the published file:
# neural_plasticity_simulation.py, lines 151-166 (commit 39a8baf)
# Recovery chance based on stimulation and neighboring activity
neighbors = self._get_neighbors(i, j)
active_neighbors = sum(1 for x, y in neighbors if self.neurons[x, y] == 1)
# Calculate recovery probability
recovery_boost = self.stimulation[i, j] * 0.1 # Stimulation increases recovery
neighbor_boost = active_neighbors * 0.001 # Active neighbors help recovery
age_factor = (100 - self.age_map[i, j]) / 100 # Younger neurons recover better
recovery_prob = self.recovery_rate + recovery_boost + neighbor_boost + age_factor
# Check for recovery
if np.random.random() < recovery_prob:
self.neurons[i, j] = 1
new_function_map[i, j] = 0.5 # Start with partial function
recovered_count += 1
Three of the four terms are small. The base rate is 0.001. A stimulation dose of 0.2 or 0.3, the values the script uses, adds 0.02 or 0.03 per dose and then fades. Eight active neighbours add 0.008. The fourth term, age_factor, is (100 - age)/100 with age drawn uniformly between 0 and 100. It is a number between 0 and 1 with a mean of 0.5, and it is added, not multiplied. In the compensation rule a few lines further down, the same kind of age factor is used as a multiplier, which is almost certainly what was meant here.
The consequence can be worked out on paper. If each damaged cell recovers with a fixed probability a drawn uniformly from 0 to 1, the expected share still inactive after n steps is the average of (1 - a)n, which is 1/(n + 1). Half the lesion is back after one step, five sixths after five, and stimulation can only nudge the numbers by a few percent.
We checked this against the code itself, with random damage events switched off so that only the main lesion counts. Each condition ran 20 times with seeds 0 to 19.
| Steps after lesion | Archived code, with stimulation | Archived code, no stimulation | Prediction 1 - 1/(n + 1) | Age term removed, with stimulation | Age term removed, no stimulation |
|---|---|---|---|---|---|
| 1 | 49.1% | 48.8% | 50.0% | 0.8% | 0.4% |
| 2 | 66.9% | 66.5% | 66.7% | 1.5% | 0.4% |
| 5 | 83.5% | 84.0% | 83.3% | 2.8% | 0.9% |
| 10 | 91.6% | 91.4% | 90.9% | 5.4% | 1.4% |
| 20 | 96.1% | 95.7% | 95.2% | 8.2% | 2.1% |
Values are the mean share of lesioned cells active again, over 20 runs. In the archived code the runs ranged from 41% to 57% after one step and from 94% to 99.5% after twenty. Stimulation made no visible difference. The prediction from the formula and the simulation agree to within about one percentage point. The same rule applies to the 20% of cells that start the run inactive, which is why the active count in the published video jumps at the very beginning.
4. What the original findings rested on
The 2024 post listed five discoveries. Here is where each one came from.
- “Neighbours matter.” Written into the compensation rule, which only acts on neighbours of inactive cells.
- “Different neurons, different responses.” Written into the type multipliers (2.0, 1.0 and 0.7) and the damage resistance (1.5).
- “Early intervention helps.” Never tested. The script applies stimulation at step 0, every 20 steps after step 30 and every 15 frames in the animation loop. No run compares an early schedule with a late one.
- “Too much work causes stress.” Written into the rule that lowers health when function exceeds 1.5.
- “Recovery takes time.” Contradicted by the code, where half of all damage reverses on the first step.
With the age term removed, recovery becomes slow and stimulation matters: 8.2% of the lesion is back after twenty steps with stimulation, 2.1% without. It is tempting to call that the corrected finding. It is not a finding. The line recovery_boost = self.stimulation[i, j] * 0.1 says that stimulation raises recovery, and the simulation reports it back. Fixing the bug turns a claim that was false into one that is true by construction.
Simulations of this kind are still useful. They show what follows from a set of assumptions, sometimes in ways that are hard to see on paper. The error in 2024 was presenting the assumptions as discoveries about the brain.
5. What the neuroscience says
5.1 Maps reorganise, and the direction matters
The README and the mirror-neuron post both cite Merzenich and colleagues (1984). After digit amputation in adult monkeys, the cortical representations of adjacent digits and the palm expanded into the territory that had represented the missing digit [1]. The mirror-neuron post described this as a “shrinkage” of the corresponding brain area. It was taken over, which is a different and more interesting result.
The same post then described a monkey whose arm had been deafferented and said that “the brain area responsible for the arm expanded to take over nearby areas, in this case, parts of the face”. The finding of Pons and colleagues runs the other way. In macaques whose dorsal roots had been cut about twelve years earlier, the face representation in area 3b had expanded by 10 to 14 mm into the territory that formerly represented the hand [2]. Deprived cortex was taken over by an intact neighbour, which is roughly what the toy's compensation rule tries to express.
5.2 Training shapes reorganisation
The result our toy wanted to illustrate exists, but it is about behaviour and maps, not cells switching back on. Earlier work had shown that a small ischemic lesion in the hand area of squirrel monkey motor cortex is followed by a further loss of hand territory in the undamaged cortex next to it. Nudo and colleagues retrained skilled hand use after similar lesions. The loss did not occur, in some animals the hand representation expanded into territory that had represented the elbow and shoulder, and skilled hand function recovered [3].
5.3 “Earlier is better” is not a safe summary
Animal work does suggest a time-limited window of heightened plasticity after stroke, and Murphy and Corbett also point out that most measured gains reflect compensation rather than true recovery [4]. A window is not a rule that sooner is always better. The AVERT trial randomised 2,104 patients at 56 stroke units in five countries. Very early, frequent, higher-dose mobilisation started within 24 hours of stroke led to fewer favourable outcomes at three months than usual care: 46% against 50%, adjusted odds ratio 0.73 (95% CI 0.59-0.90) [5]. The authors concluded that early, lower-dose out-of-bed activity is preferable. Timing interacts with dose. Our toy has no notion of either.
5.4 Mirror neurons and mirror therapy
Mirror neurons were first described in the macaque premotor area F5: cells that fire both when the monkey performs an action and when it watches the same action [6]. Evidence for a comparable system in humans comes mostly from imaging and stimulation studies. How much these cells explain about understanding, imitation or learning is contested. Hickok argues at book length that the central claims are overstated [7]. The 2024 page called mirror neurons „die Geheimwaffe des Gehirns für Heilung und Lernen“, the brain's secret weapon for healing and learning, and said their discovery had “revolutionized” our understanding of the brain. Neither phrase holds up.
The post also used mirror therapy as evidence. In mirror therapy a patient watches the reflection of the healthy limb in a mirror placed where the affected limb would be seen. A Cochrane review found moderate-certainty evidence that it improves motor function after stroke (standardised mean difference 0.47; 36 studies, 1,173 participants), with effects depending on the comparison treatment [8]. The therapy works through a visual illusion. Its evidence base does not depend on mirror neurons, and it does not confirm them. The post's claim that patients who first observe movements progress faster than those who only practise them came without a source, and we could not identify the study it relied on, so we drop it.
6. What a toy would need before it could say anything
We are not planning to extend this model, but the list is useful for anyone who wants to build one:
- Units connected by weights, so that activity propagates and damage removes inputs as well as cells.
- A learning rule, Hebbian with homeostatic limits, so that “plasticity” means changing connections.
- A task with a readout, so that recovery is measured as restored function rather than as a count of switched-on cells.
- Dose and timing of stimulation as explicit variables, swept over a grid fixed in advance.
- Seeds, confidence intervals and an ablation for every mechanism the write-up mentions.
Even a model that met all of these and reproduced the preserved hand maps of Nudo and colleagues would show only that its mechanism is sufficient inside the model. It would say nothing about what happens in a patient.
7. What this means for enterprises
Ablate before you announce. The cheapest test that would have stopped the 2024 post takes a minute: set stimulation to zero and see whether recovery changes. It did not. The same check belongs in every analytics or ML pipeline that claims an effect. Remove the feature, the treatment or the intervention and confirm that the effect goes away. If it does not, the claim is unsupported. If the effect is a term in your own formula, the claim is an assumption and should be labelled as one.
Check the magnitude of every term in a probability. The bug survived because four terms were added that lived on different scales. A unit test that asserts “with no stimulation and no neighbours, recovery stays near the base rate” would have failed on the first run. Property-based tests of this kind are cheap and catch a class of errors that code review rarely does.
Optimistic recovery assumptions hide the failure you are modelling. What the grid actually simulates is closer to a cluster than a cortex: failed units, neighbours that absorb their load, and wear when they are pushed past capacity. In that reading, the bug is a node that heals itself half the time on every tick. Any capacity plan built on such a model would look safe. When you simulate failover, queues or recovery times, look first at how recovery is modelled, because that is where wishful thinking tends to sit.
8. Reproducibility
Code. github.com/kim266/neural_plasticity_simulation, commit 39a8baf (9 April 2025), which matches our archived copy. Python 3 with NumPy and Matplotlib.
Audit. We copied the file to a separate folder, imported the class without the animation, and ran 20 seeds per condition with np.random.seed(seed), seeds 0 to 19. Settings follow the published script: grid 50, lesion at (25, 25) with radius 8 and intensity 1.0, initial stimulation of 0.2 at (27, 27) with radius 4. Random damage events were switched off. “No stimulation” replaces apply_stimulation with a function that does nothing, which removes both the initial dose and the automatic doses inside update(). “Age term removed” sets every cell's age to 100, which makes the added term zero. The measure is the share of cells destroyed by the lesion that are active again after 1, 2, 5, 10 and 20 calls to update(). The whole audit runs in under 20 seconds on a laptop.
# condensed from our audit script; in_circle() returns a boolean mask
np.random.seed(seed)
sim = NeuralPlasticitySimulation(grid_size=50)
sim.random_damage_prob = 0.0
if not stimulate:
sim.apply_stimulation = lambda *a, **k: None
if remove_age_term:
sim.age_map[:] = 100.0 # (100 - age) / 100 becomes 0
sim.damage_region(25, 25, 8)
if stimulate:
sim.apply_stimulation(27, 27, 4, strength=0.2)
lesion = in_circle(25, 25, 8) & (sim.neurons == 0)
for t in range(1, 21):
sim.update()
share_back = (sim.neurons[lesion] == 1).mean()
Video. The original animation is kept below, unedited, as a record of the bug.
References
- Merzenich, M. M., Nelson, R. J., Stryker, M. P., Cynader, M. S., Schoppmann, A., & Zook, J. M. (1984). Somatosensory cortical map changes following digit amputation in adult monkeys. Journal of Comparative Neurology, 224(4), 591-605. doi:10.1002/cne.902240408
- Pons, T. P., Garraghty, P. E., Ommaya, A. K., Kaas, J. H., Taub, E., & Mishkin, M. (1991). Massive cortical reorganization after sensory deafferentation in adult macaques. Science, 252(5014), 1857-1860. doi:10.1126/science.1843843
- Nudo, R. J., Wise, B. M., SiFuentes, F., & Milliken, G. W. (1996). Neural substrates for the effects of rehabilitative training on motor recovery after ischemic infarct. Science, 272(5269), 1791-1794. doi:10.1126/science.272.5269.1791
- Murphy, T. H., & Corbett, D. (2009). Plasticity during stroke recovery: From synapse to behaviour. Nature Reviews Neuroscience, 10(12), 861-872. doi:10.1038/nrn2735
- AVERT Trial Collaboration group. (2015). Efficacy and safety of very early mobilisation within 24 h of stroke onset (AVERT): A randomised controlled trial. The Lancet, 386(9988), 46-55. doi:10.1016/S0140-6736(15)60690-0
- Rizzolatti, G., & Craighero, L. (2004). The mirror-neuron system. Annual Review of Neuroscience, 27, 169-192. doi:10.1146/annurev.neuro.27.070203.144230
- Hickok, G. (2014). The Myth of Mirror Neurons: The Real Neuroscience of Communication and Cognition. W. W. Norton. ISBN 978-0-393-08961-5. openlibrary.org/isbn/9780393089615
- Thieme, H., Morkisch, N., Mehrholz, J., Pohl, M., Behrens, J., Borgetto, B., & Dohle, C. (2018). Mirror therapy for improving motor function after stroke. Cochrane Database of Systematic Reviews, 2018(7), CD008449. doi:10.1002/14651858.CD008449.pub3
Changelog
- “Simulating Brain Healing: How Neurons Adapt After Injury” published on the Senva blog, together with the companion page “Spiegelneuronen: Die Geheimwaffe des Gehirns für Heilung und Lernen” (German title, English text).
- Code published on GitHub (commits
95f1bc1and39a8baf). - Both pages merged and rewritten as this Labs paper. The recovery bug is documented with a seeded audit. The claims that stimulation and early intervention help recovery are withdrawn. The description of Pons et al. (1991) is corrected, mirror-neuron claims are qualified, the AVERT trial is added, and a not-medical-advice note is included. Status set to exploratory.

