How some of the answers in FIDELITY.md were arrived at, kept for the record. Nothing here is needed to use pyVIDE. It is here because several of these answers took more than one attempt, and the failed attempts are worth recording.
Three times the obvious reading of VIDE's C was the wrong one, and reading the line more carefully never helped. What settled each case was the surrounding C: the types, and the places the same value is used elsewhere.
e_computer is not E(z). VIDE's generateMock.cpp:150 displaces the
line-of-sight coordinate with z += v/(100*e_computer(z0));, which reads like
v / (100 E). Earlier in the same file, TotalExpansion::operator() returns
1/sqrt(Omega_M*cube(1+z) + Omega_L), the inverse expansion function. The
proof is elsewhere in the same file, where the same object is integrated to get
a comoving distance, and the integrand of D(z) is 1/E, not E. So VIDE's
displacement is doRSD=False, so the stages that check every
other number in the pipeline say nothing about that line. tests/test_rsd.py
now transcribes TotalExpansion independently and asserts both that pyVIDE
matches it and that the wrong reading is measurably different, so the test can
actually fail.
runsum is not a plain sum. In vozutil.c::vorvol, the squared
displacement that positions every Voronoi half-plane is accumulated in a C
float while the products around it are doubles. That moves every plane by
about
A stored type is not an evaluation type. pruneVoids.cpp:626 decides
membership of the central sphere with if (sqrt(dist2) < centralRad). Both
operands are C floats, so the natural reading is a single-precision
comparison, but sqrt() returns a double and centralRad promotes to meet
it, so the comparison happens in double. Rounding to float32 first would move
any member whose distance sits within half a float32 ulp of the boundary, and
that void's centralDen would be off by 1/numCentral, 30 to 50 % for a
typical count of two or three. The rate is about one member-test in centralDen exact even against an implementation
that got this wrong.
'fast' falls back to the exact route for a cell whenever that cell touches a
guard point, or its corner is hard to locate precisely. That is not a guarantee
of agreement everywhere. On a well-buffered run with no guard warnings, 15
cells out of 3 766 742 came out different from 'exact', by a few parts in a
million, and none of them was one of those two kinds. Why they differ is not
known. One configuration that can potentially produce such a difference is
known: neighbours lying almost exactly on a common sphere, as on a regular grid
with tiny displacements. On a 16^3 lattice displaced by 1e-4 of the spacing, 8
of 4096 cells differ from the values using 'exact' in VIDE_halos and none
in float64, and the per-cell check does not flag them, because the tetrahedra
involved are not flat. Whether the 15 cells above are of this kind has not been
checked.
The obvious suspect was a very flat tetrahedron, which is exactly the case that
makes a corner hard to place. Sending those cells down the exact route as well
changed nothing, so that is not the reason either. On realistic tracer sets the
effect has never appeared on a test box small enough to ship and the lattice
above is only an artificial configuration where it might appear. The only
evidence for real catalogs is the two full-catalog comparisons, and the honest
scope of 'fast' is the measured one in FIDELITY.md.
Three details of doRSD='VIDE' cannot be read from VIDE's repository at all.
They live in a struct the build downloads from CosmoTool, so the source you can
clone does not contain them: whether the peculiar velocity and Omega_M reach
the displacement as float32 or at full precision, and whether the redshift
arrives through a float32 scale-factor round trip.
pyVIDE once guessed all three from a third-party copy of that struct, and one
guess was wrong: there is no scale-factor round trip, so the redshift arrives
undegraded. Only a comparison against VIDE's own output could settle it, and
that comparison is now stage S5. The three casts in rsd.py are measurements.
Do not replace them with what a copy of the struct appears to say.
The claims about VIDE in these docs do not all rest on the same thing.
Most of them are measured. The table in FIDELITY.md compares
whole catalogs against a frozen VIDE run, column for column and row for row, at
five merging thresholds and across all eight pruned variants. Every column VIDE
also writes is covered there, so "densCon matches VIDE" rests on one run
against another, not on anyone's reading of the source. The
'pyvide'-against-'VIDE_halos' numbers in that page come from two scripts in
the Zenodo dataset record next to the harness: compare_modes.py lines two
runs of the same tracers up on input rows, pairs their zones by core particle
and reports what differs; compare_merging.py does the same for the merged
voids of two catalogs at the same threshold, comparing the set of zones each
void absorbed.
The rest are read from VIDE's code: that isLeaf means "has a parent", that
jozov2 leaves single-tracer zones out of voidDesc, that VIDE keeps only the
rescaled centralDen, that its scripts feed mergingThreshold into
maxCentralDen. These agree with the measurements, but no measurement tests
them one at a time, and this page opens with three cases where a plausible
reading was wrong.
So a page saying pyVIDE reproduces a VIDE number is the first kind of evidence. A page explaining why VIDE behaves as it does is the second.
A few figures in the documentation come from single runs on data that is not shipped, and they are marked "(measured)" wherever they appear. They are not reproducible from this repository, and they are not tests. The ones that are tests carry "(checked by tests/…)" instead, and you can run those yourself.