Add more column options to p-adic field dynamic statistics - #7163
Open
roed-math wants to merge 6 commits into
Open
Add more column options to p-adic field dynamic statistics#7163roed-math wants to merge 6 commits into
roed-math wants to merge 6 commits into
Conversation
Extend LFStats.dynamic_cols from just galois_label/slopes to every
searchable column (p, n, e, f, c, galois_label, aut, u, t, top_slope,
slopes, visible, hidden, ind_of_insep, associated_inertia, jump_set), so
users can build their own statistics and click through to matching
searches. Supporting display metadata (short_display, top_titles,
knowls, formatters, sort_keys, query_formatters, default p/c buckets) is
added to match the search boxes. sort_keys map None to a first-sorting
sentinel so columns with NULLs (slopes, hidden, u, t, galois_label) no
longer crash when picked unconstrained; query_formatters emit valid
search URLs (topslope=, slopes=...&slopes_quantifier=exactly, empty
constraints for un-searchable values). galformatter/galsortkey/galquery
now tolerate the 3,996 NULL galois_labels. discdisp pins buckets={} so
the static /stats page is unchanged. Links to the dynamic stats page are
added from the browse index (short_summary) and /stats (summary).
Verified: sage -python -m pytest lmfdb/local_fields/test_localfields.py
(10 passed, incl. new test_stats_pages/test_dynamic_stats); /padicField/stats
byte-identical to base except the added "create your own" link (fixed
PYTHONHASHSEED diff); formatter/sort-key/query-formatter sweep over all
distinct DB values of the new columns with no errors; new-style
click-through URLs resolve (e.g. slopes exact match returns 10 fields);
pyflakes clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mic stats (LMFDB#6542) P2: the dynamic-statistics query_formatters encoded not-computed/null buckets as empty url parameters (gal=, u=, slopes=, associated_inertia=), which the search parsers silently ignore -- so clicking a null bucket's count opened an UNFILTERED search returning every field instead of the counted records. There is no url-level null-search syntax (empty params are dropped; $exists:False is not reachable from any parser used by common_parse), so the drill-down link is now suppressed for such buckets. The null query_formatters return a new NO_SEARCH_QUERY sentinel; LFStats.display_data (via the testable _suppress_null_links helper) blanks any assembled drill-down url containing it, and stat_1d.html now guards the link with {% if c.query %} exactly as stat_2d.html already did. P3: formatbracketcol handled empty lists/strings but not None, so ind_of_insep/ associated_inertia could render a literal $None$ bucket label; None now maps to the standard "not computed" presentation. Verified (sage -python, devmirror): pytest lmfdb/local_fields/test_localfields.py -> 12 passed, incl. two new tests (unit coverage of the sentinel query_formatters, _suppress_null_links for counts+grid, and formatbracketcol(None/''/[]); page-level coverage that the galois_label/slopes/hidden not-computed buckets render with no empty-parameter link and no sentinel leak, while non-null buckets still filter correctly). Confirmed the not-computed galois_label bucket (3996 fields) now has a blank query, and non-null drill-downs (p=2,n=4 -> 12 cyclic quartics; n x e) still produce correct filtered links. pyflakes clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three ways a count on the dynamic statistics page could link to a search returning different records than the count, all of them in the generic statistics framework rather than the p-adic tables: Cells of a two-dimensional grid with no records were synthesized by KeyedDefaultDict from the formatted row and column headers, so their urls were built from displayed values (TeX, html, "not computed") rather than stored ones. The totaler intersects the urls of a row to find the row's constraint, so a sparse row lost it: the "not nilpotent" total on the abstract groups statistics page linked to /Groups/Abstract/? and returned all 1.5 million groups instead of the 455903 counted. display_data now indexes counts by the stored values and builds every url, empty cells included, from those, so a formatter is free to produce TeX or html. Values that display identically share a row, adding their counts, rather than one silently replacing the other. Drill-down urls were serialized from the parsed query, whose columns are often not parameters the search page accepts: dynamic statistics constrained by Artin slopes produced slopes_tmp=2A, which the p-adic parser ignores, so clicking a count opened a broader search. dynamic_setup now passes the search boxes the user filled in as link_constraint, which reproduce the same query by construction, and a test asserts they re-parse to it. Bucket endpoints for top_slope were compared as text against the fixed-width decimal encoding the column is stored in, so a bucket of 1-2 counted the wrong fields, and topslope_query sliced 12 characters off every endpoint, turning the bucket 1-2 into topslope=-. Buckets are now encoded through a bucket_encoders hook before they reach the backend and decoded for display and links, and an endpoint that is not a rational is rejected with the usual message. Along the way: the sentinel for unsearchable values moves into the framework, so a null bucket is linkless in every table rather than only in p-adic ones; totals that share no constraint are no longer linked; total urls list their parameters in a fixed order rather than set order; invalid input to the dynamic statistics page flashes an error instead of raising a 500; the default p and c buckets are left open above so no field is omitted as the database grows; a not-computed jump set is distinguished from an empty one; and nilp_qformatter maps the stored -1 to nilpotent=no, since nilpotency_class=-1 matches nothing. Every statistics page in LMFDB renders identically to before apart from those fixes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s it The total row appended the bare column name to the url as a marker, which is not a search constraint: an empty parameter is ignored by the parsers, so the link returned every record rather than the ones counted, and the parameter is often not even one the search page accepts (galois_label rather than gal). The statistics backend computes a total over the records where the column is not null, so the discrepancy is real wherever a column is not computed for every record. On the classical modular forms statistics page the analytic rank block totalled the 281885 forms whose analytic rank is known and linked to a search returning all 1141510 newforms; dynamic statistics for Galois groups with p=7 and n=21 totalled 1324 of 3784 fields. A total is now linked only when the search page can describe exactly the records it counts: the constraint itself, which is right when the column is computed for every record satisfying it. Totals over buckets (which cover only the buckets displayed), over split lists (which count entries rather than records), and over a column the constraint also restricts (whose parameters the urls leave out, so that each count can constrain it) are rendered without a link. Also fixes the test helper that reads a one-dimensional table off the page: it matched nothing, so two page-level loops were passing vacuously. With it working, the pairing of an addl_row_title row with its values turns out to have been repaired too, by the same change that made the headers carry their own values: on the genus 2 statistics page the real geometric endomorphism algebras were rotated against the counts underneath them, labelling the 6 curves with endomorphism algebra C x C as M_2(R). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LMFDB uses American spelling, so "labelled" becomes "labeled" and "totalled" becomes "totaled". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #6542.
The dynamic statistics page for p-adic fields previously offered only Galois group and Galois Artin slopes as columns. This extends
LFStats.dynamic_colsto every searchable column (residue characteristic, degree, ramification index, residue field degree, discriminant exponent, Galois group, automorphisms, unramified/tame degree, top slope, Galois/visible/hidden slopes, indices of inseparability, associated inertia, jump set), with display metadata and click-through query formatters matched to the existing search boxes.Sort keys map not-computed (NULL) values to sort first, so columns with NULLs no longer crash when selected unconstrained, and Galois-group handling tolerates fields with no computed Galois group. Default
p/cbuckets are provided, and the static statistics page is verified unchanged (discdisp pins empty buckets).Links to "create your own" statistics are added from the browse index and the statistics page. Adds tests covering the links and rendering of all new columns.
Ported from roed-math#27, where the full write-up and comment history live.
🤖 Generated with Claude Code