Keep reading
You are hereRecompute matched circles in a toy three-torus
The shape of space · Reading path
By the end of this guide you will have run one Python script that builds a periodic sky, finds the true circle pairs of a cubic three-torus, scores them against 300 random false pairs, and shows four ways the test can fail. Everything runs from three saved files with the Python standard library alone. The method follows the circle statistic of Cornish, Spergel and Starkman and the false-pair threshold used by Planck. The model is a toy: it has no real microwave physics, no beam and no mask, and its numbers are not a reanalysis of any satellite map.
Read the chapter on telling a real match from a lucky one first. It derives every formula used below.
Download the script, the saved inputs and the expected output into one empty folder. The script imports only json, math, random and sys. The expected output was produced with Python 3.9.6 and reproduced with Python 3.14.3. The two runs agree in every number and differ only in the recorded version string. A run takes about 20 seconds on a laptop.
From that folder, run:
python3 -I recompute_matched_circles.py tutorial-inputs.json my-output.jsonThe flag -I keeps Python from loading modules from the current folder or your environment, so the run uses only the standard library.
The inputs file holds four runs. Each sets the same quantities:
{"boxSide": 1.2, "bumpWidth": 0.08, "bumpCount": 3000, "seed": 86, "noiseRatio": 0.5, "circleSamples": 64, "falsePairTrials": 300, "falsePairRadiiDegrees": [10, 20, 30, 40, 50, 60, 70, 80]}Lengths are in units of , the comoving distance to the last-scattering surface, so the sphere we see has radius 1. The box edge is = boxSide. Angles are in degrees. Temperatures are in units of the signal's standard deviation on the sphere, so noiseRatio is , the inverse of the signal-to-noise ratio .
The sky is a sum of 3000 Gaussian bumps of width = bumpWidth, at random positions in the box, each with a random Gaussian weight. Every bump is copied onto all lattice images that can reach the sphere, which is what makes the field periodic. Two points a distance apart are then correlated in proportion to , summed over images. The Lab builds its sky differently, from Fourier modes, so the two give different skies with the same kind of spots. Compare the behaviour, not the digits.
The four runs are wrapped-box with , near-the-limit with , larger-than-the-view with , and noisy-sky, which repeats wrapped-box with noise at twice the signal.
Open my-output.json at runs, then wrapped-box. The first number to read is periodicityDifference. It compares the field at a point and at the same point moved by one box edge. It must be exactly zero. A non-zero value means some lattice images were left out of the sum, and every circle score after it would be wrong.
The list predictedPairs has one entry for each pair of images closer than 2. For there are nine: three with separation and radius , six with separation and radius . These radii come from .
For each pair the script samples 64 points on the circle around and the same 64 physical points moved by , which lie on the circle around . Without noise, statisticAtZeroShift is for all nine, and bestShiftSamples is 0. The two circles carry identical temperatures, point by point. If you see a best shift other than zero here, the two circles were sampled with different starting directions.
The value noisyStatisticAtZeroShift adds independent noise to each circle. Equation 5 of the 1998 paper predicts for noise at half the signal, and the output records that prediction as css1998Equation5. The nine noisy values average .
A blind search cannot score only the true pairs. It must try every centre and radius, and keep the best rotation of each. The block falsePairs does this for 300 back-to-back pairs on random axes, at radii drawn from 10 to 80 degrees, with the same noise as the noisy true pairs.
Read two numbers. singleShift.standardDeviation is the spread at a fixed rotation: , wider than the independent-sample value that the output stores next to it. Neighbouring samples share spots, so the circle carries fewer independent values than 64. bestOverShifts.percentile99 is the false level that 1 percent of random pairs exceed after choosing their best rotation: . With 300 trials it is the fourth-largest value.
| Run | Box edge | True pairs | True best scores | False 1 percent level |
|---|---|---|---|---|
| wrapped-box | 9 | to | ||
| near-the-limit | 3 | , , | ||
| larger-than-the-view | 0 | none | ||
| noisy-sky | 9 | to |
In wrapped-box every true pair clears the false level. That is a detection in this toy sky.
A box larger than the view. In larger-than-the-view the list predictedPairs is empty, because no image is closer than 2. Yet the best false pair still scores . A search that reported its top score without a threshold would announce circles in a sky that has none. This is the unidentifiable limit: the circle test gives the same answer here as for infinite flat space.
Noise that drowns the match. In noisy-sky the prediction falls to at the correct rotation. After choosing the best rotation the true pairs score to , and only one of nine exceeds the false level . The topology is still there, but this map cannot show it.
Small circles near the limit. In near-the-limit the circles have radius . Their samples are packed closely and share spots, so the false level rises to and one of the three true pairs, at , falls below it. This is the same mechanism that sets the smallest circle radius in the Planck search.
A wrong orientation. The value mirroredBestStatistic compares each true circle with its partner read in the opposite direction. It is not a match, yet after choosing the best rotation it scores to . Two traces of a smooth sky can line up well over part of a circle by accident. So the search must fix the orientation the topology predicts, and judge the best score against false pairs searched the same way.
The scores are rounded to four decimals. The 1 percent false level comes from the fourth-largest of 300 values, so its own uncertainty is a few hundredths: with noise at half the signal, the three runs give , and . A real analysis uses far more simulations and the exact pipeline of the data. Planck used 300 full simulations of its maps.
The noise model adds independent Gaussian noise to every sample. Real maps have noise that varies across the sky, regions removed by a Galactic mask, and contributions from gas velocity and from changing gravitational potentials that differ between the two paths. None of those is in this script, so its results describe how the method behaves.
In the Lab, choose a preset, then use the export button in the data row. The exported record lists the predicted pairs, their radii and the box-axis score with its chance level. Check that the pair count and radii agree exactly with predictedPairs for the same box edge. The scores will differ in detail because the two skies differ, but true pairs should sit near 1 without noise and sink towards the chance band as noise grows.
Sources: Cornish, Spergel and Starkman 1998, equations 5, 6 and 8, Planck 2015 results XVIII, sections 4.2 and 5.1.1, COMPACT collaboration preprint on noise sources for the circle signal.
Export the Lab record and compare its circle scores with your script output.
You are hereRecompute matched circles in a toy three-torus
The shape of space · Reading path