Location: source_modelling/community_fault_model.py:483
What happens: In nodal_plane_from_neighbours, the two vote sums are near-identical, but the weight inside nodal_plane_2_votes still references nodal_plane_1.strike:
469: nodal_plane_1_votes = sum(
473: * abs(line_segments[segment] - nodal_plane_1.strike + 1e-5) # correct
476: if abs(... - nodal_plane_1.strike) < abs(... - nodal_plane_2.strike)
479: nodal_plane_2_votes = sum(
483: * abs(line_segments[segment] - nodal_plane_1.strike + 1e-5) # <-- should be nodal_plane_2
486: if abs(... - nodal_plane_1.strike) >= abs(... - nodal_plane_2.strike)
The filter at :486-487 is correct — it selects segments closer to plane 2 — but the weight at :483 measures those segments against plane 1's strike.
Why that's wrong: The weight is 1 / (distance * strike_misfit), so it is meant to reward segments whose strike closely matches the plane being voted for. By construction, every segment counted at :486 has a larger misfit to plane 1 than to plane 2, so using plane 1's misfit in the denominator systematically shrinks plane 2's weights. The bias always runs one way: nodal_plane_1 wins ties and near-ties it should lose. The symmetry with :473 makes the intent unambiguous.
How to reproduce: Take a point near trace segments whose strikes sit just closer to nodal_plane_2.strike than to nodal_plane_1.strike. Each such segment contributes 1/(d * |seg - np1|) instead of the intended 1/(d * |seg - np2|); since |seg - np1| > |seg - np2|, the contribution is too small and nodal_plane_1_votes >= nodal_plane_2_votes at :490 returns nodal_plane_1.
Suggested direction: Change nodal_plane_1.strike to nodal_plane_2.strike at :483. Factoring the weight into a small helper taking the plane as an argument would prevent the two branches drifting again.
Confidence: high
Location:
source_modelling/community_fault_model.py:483What happens: In
nodal_plane_from_neighbours, the two vote sums are near-identical, but the weight insidenodal_plane_2_votesstill referencesnodal_plane_1.strike:The filter at
:486-487is correct — it selects segments closer to plane 2 — but the weight at:483measures those segments against plane 1's strike.Why that's wrong: The weight is
1 / (distance * strike_misfit), so it is meant to reward segments whose strike closely matches the plane being voted for. By construction, every segment counted at:486has a larger misfit to plane 1 than to plane 2, so using plane 1's misfit in the denominator systematically shrinks plane 2's weights. The bias always runs one way:nodal_plane_1wins ties and near-ties it should lose. The symmetry with:473makes the intent unambiguous.How to reproduce: Take a point near trace segments whose strikes sit just closer to
nodal_plane_2.strikethan tonodal_plane_1.strike. Each such segment contributes1/(d * |seg - np1|)instead of the intended1/(d * |seg - np2|); since|seg - np1| > |seg - np2|, the contribution is too small andnodal_plane_1_votes >= nodal_plane_2_votesat:490returnsnodal_plane_1.Suggested direction: Change
nodal_plane_1.striketonodal_plane_2.strikeat:483. Factoring the weight into a small helper taking the plane as an argument would prevent the two branches drifting again.Confidence: high