How the results are checked

Every method in the app is checked against something outside its own code. The checks are:

The checks run as automatic tests on every change, so a result that drifts is caught before it is released. The test named in each row below is the one that keeps checking it.

Stereonet and statistics

What Checked against Result Test
Kamb contours Vollmer (1995), Computers & Geosciences 21: for 50 readings the expected count is 7.63 and sigma 2.54 Same to 0.005 Kamb n=50: expected count 7.63 (Vollmer 1995)
Kamb contours A second program that counts readings one by one with explicit angles Same at 60 random points to 10⁻⁹ Kamb: matrix implementation == brute-force angle counting
Schmidt (1%) contours A one-by-one count of the readings inside a 1% circle Same to 10⁻⁹ schmidt: the counting circle covers 1% of the net
Fisher contours Theory: averaged over the whole net, the density of any data is exactly 1 Averages 1 fisher: the density of ANY data set averages exactly 1
Plotting position and poles Hand calculation: a plane dipping 55° toward 200° has its pole plunging 35° toward 020° Exact known plane: dip 55 toward 200 has its pole plunging 35 toward 020
Mean, Fisher kappa and 95% cone The first, separately checked version of the maths, run in Posit Mean pole 53.1° / 199.7°, cone 3.03°, same cluster: Fisher 95% cone 3.03 deg
Principal axes and fold axis Theory: for a girdle, the smallest axis is the pole to the girdle Same to 10⁻⁹ principal axes: for a girdle the minimum axis is the pole to the girdle
Intersection of two planes Hand calculation: planes 30/090 and 40/180 meet at plunge 25.4°, trend 124.5° Same to 0.001° plane intersection: planes 30/090 and 40/180 meet at plunge 25.4 trend 124.5
Rotation Theory: rotating does not change the angles between readings Spread unchanged rotation preserves the spread
Unfolding A folded bed made with a known fold The girdle becomes a tight cluster noisy fold: unfolding turns a girdle into a tight cluster
Rose confidence of the mean 400 simulated samples with a known mean direction The 95% wedge holds the true mean about 95% of the time rose wedge: simulated von Mises samples are covered about 95% of the time
Orientation sets Five data sets made with three known sets plus 10% scatter 3 sets found every time, axes within 3°, 90% or more of readings in the right set three sets + 10% scatter: k = 3 recovered on 5 of 5 datasets
Orientation sets Readings spread evenly, with no sets No sets found uniformly random orientations: no sets found

Oriented core (alpha / beta)

What Checked against Result Test
Alpha / beta to dip and dip direction Planes of known orientation turned into alpha / beta and back, for 4 hole attitudes × 5 planes × all 16 conventions Worst error under 0.01° alpha/beta round trip over
The app’s default convention acQuire’s own stored procedure QSP_STRUCTURE_CALC, on 200 random readings Same to a millionth of a degree acQuire procedure: alpha / beta to a plane equals the app's default convention
The convention check Data made with a known convention, in holes drilled four ways Picks the true convention convention check: holes in four directions recover the true convention
The convention check Holes that are nearly parallel, which cannot tell conventions apart Says it cannot decide, rather than guessing convention check: nearly parallel holes are reported as not decidable
The default convention on real data A mining site’s own calculated dips (729 oriented-core readings; the data are private, so this is not in the automatic tests) Median difference 0.14°; 92% within 5° Checked once (tools/convention_vs_reference.R)

Drillholes

What Checked against Result Test
Sampling-bias (Terzaghi) correction Readings drawn from a known 50 / 50 mix of steep and flat planes, as a vertical hole sees them Weighting restores the 50 / 50 mix terzaghi: a vertical hole sees few steep planes
Fracture frequency and spacing Structures placed evenly a known distance apart Known frequency and spacing frequency: evenly spaced structures give the known frequency
RQD from the depths A worked example by hand (pieces of 0.25, 0.05, 0.40, 0.20, 0.30 and 0.80 m in 2 m) 97.5% RQD from depths: a worked example
RQD from frequency Priest and Hudson (1976): 73.6% at 10 fractures a metre Same to 0.001 RQD from frequency (Priest and Hudson 1976)

What has not been checked

  • No side-by-side run with Dips, Stereonet 11 or Orient on the same file. The methods are checked against published values and hand calculations, not against those programs’ output.
  • The mean, kappa and cone are checked against the first version of the maths (the proof of concept, run separately in Posit). They have not been checked against a published worked example.
  • The Bingham confidence ellipse is checked only against that first version.
  • The cluster / girdle label uses Woodcock’s K = 1 rule. It is a convention, not a significance test.
  • Sets closer together than about twice their spread cannot be told apart. The test above shows two sets 9° apart with a 7° spread found as one.
  • Alpha / beta conventions differ between sites. The real-data check above shows the default fits one site’s data. Use the convention check, and a few structures of known orientation, for your own.

The tests are in the project’s tests folder, and they all run before every release.