Add correspondence quality panel into Studio analysis - #2641
Merged
Conversation
Brings the correspondence-quality metric into the Analyze pane. Each sample is reconstructed through Studio's own mesh warper, so the score matches the reconstruction on screen, and the per-vertex distance colors both the surface and the particles. Samples can be sorted by mean, median or max distance, and that ranking can reorder the All Samples view so the challenging shapes come first. CorrespondenceEvaluation gains an in-memory entry point shared with the command line, plus median distance in the report, CSV and Python API. Along the way: the box plot no longer keeps its auto-assigned color after an explicit setColor, ParticleAreaPanel takes the job's double progress instead of truncating it to an int, and the lightbox refits its shared camera when the tile layout changes.
JKQTPLOTTER_VER named a branch, so any push to it silently changed what every clean dependency build fetched, with nothing in this repo recording the change. It now names the tag v2026.08.24-tick-labels on the fork's develop branch, which adds minor tick label collision avoidance to the axes. Future dependency changes get a new tag and a bump here, so they are visible and revertible.
The chart now plots the ranked metric together with the max distance on a log axis, with median and p95 marked. A few swapped correspondence points leave most of the surface intact, so the mean barely moves while the max spikes, and a single-series chart would hide exactly the failure the panel exists to find. A "Localized (max / mean)" sort metric ranks by how concentrated the error is. Normalization now applies to the summary as well as the table, chart and sort, and moved out of the Sort group since it is a units option for the whole panel. The lightbox defers its camera refit to the end of the update cycle and waits for the surface to arrive: the tile layout changes before the new shapes are handed over, so fitting immediately framed whatever the previous mode had left on screen.
Adds a 6.9.0 release notes section covering the new Analyze panel, the median distance now reported by the correspondence-quality command, and the fixes to the particle area progress bar and box plot colors. Refreshes the Studio analyze page where the sort options and the normalize scope had moved on.
The samples table's "Copy to Clipboard" was written against that one widget, so the Correspondence Quality results could not reuse it. Lifted into StudioUtils as copy_table_to_clipboard() plus add_table_copy_menu(), and wired to both tables. Hardened on the way across: header items are no longer dereferenced without a null check, and values containing a comma, quote or newline are quoted with embedded quotes doubled, so the copied text is valid CSV.
The localization ratio was built from the max distance, which is a single vertex and moves with one bad triangle; on real data the max runs to more than twice the 99th percentile. Rows now carry p99_dist and norm_p99, reported in the table, the CSV and the Python API, and the ratio and its chart series use p99 instead. Clicking a table row shows that sample on its own, which is the quickest way to work down the ranking. Adds the first tests for CorrespondenceEvaluation, over the in-memory entry point shared by the command line and Studio, including the localized-defect case the metric exists to catch. Also fixes the Shape/Scalar progress bar, which truncated its fractional progress the same way particle area did.
Clicking a row switched to the single sample view with no way back except the All Samples radio at the top of the Analyze pane, which is a long way from the panel and may be collapsed. Clicking the sample that is already showing now returns to the grid.
setStretchLastSection put all the spare width on the last numeric column, so Max sat half empty while sample names were elided. The name column now takes the slack and the numeric columns size to their contents, right aligned so the decimal points line up. Column headers carry tooltips saying what each statistic is measured over, since the summary's p95 is across samples while the table's p99 is across the vertices of one sample, and the two sit close enough together to look related.
The name column elides most names at the panel's width, and the tooltip only carried the bounding box diagonal, so there was no way to read the whole name.
Shape::set_point_features() does not only store the per-particle values, it also interpolates them back over the reconstructed mesh under the same name. Handing it the sampled distances to color the glyphs therefore replaced the measured per-vertex field with an interpolation of it. The reconstruction passes through the particles, so the distance at a particle is near zero and the real error sits between them. The overlay was showing a near-zero field, hiding exactly the localized failures the panel exists to find, while the table and chart, which read the measured field, were correct. The job now keeps the per-vertex fields and the panel re-applies them after setting the point features.
Sampling the distance field at each particle gave every glyph the same near zero value: the warp inserts the particles as mesh vertices and maps them onto this shape's particles, which sit on its surface, so the distance there is zero by construction. The glyphs carried no information. Each vertex is now assigned to its nearest particle and the distances averaged over that neighbourhood, so a glyph reads as how badly the surface around it is explained. Euclidean rather than the geodesic assignment ParticleArea uses, which needs a heat solve per particle and would be far too slow over a whole cohort.
The combo read "Localized (max / mean)" while the code has used p99 / mean since p99 was added, and the docs papered over it by noting the ratio is really built from p99. Renamed to "Localized (p99 / mean)", with a tooltip saying what a high ratio means, and the docs now explain the ratio instead of correcting the label.
The section had grown to thirteen paragraphs with no subheadings, against one to three for every other panel on the page. Split into Reading the results, Finding the challenging shapes, and Seeing where it breaks down, and moved the groomed mesh caveat up next to the description of what is measured. The chart paragraph still said the second line is always the max distance, which stopped being true when the localized ratio moved to p99. It now says which line is drawn for which sort.
This ships in 6.8, not 6.9, so the separate 6.9.0 section is gone and its entries merged into the matching 6.8.0 groups. The per-subject median and p99 statistics went into the existing correspondence-quality bullet rather than standing alone, since the command and the statistics land in the same release.
The template decides what every sample is reconstructed from and which row is excluded from the statistics, so choosing it belonged next to the measurement rather than only in Surface Reconstruction. Adds the same Median button, index spinbox and name label used there. It drives the one setting rather than a second copy of it: the panel asks the analysis tool to change the template, which keeps the reconstruction panel in step, and the tool mirrors the value back. Run rebuilds the warper first, since the spinbox only records the choice, and a template change discards results measured against the previous one, from whichever panel it was made.
Resetting the panel stopped it claiming the feature map, but nothing told the viewer, so the samples kept the distance colors and the feature map field kept naming them after the results behind them had gone. It now asks for a redisplay when it had results to discard. The template name label also sized its own grid column, so every control beside it shifted as the name changed length while stepping the spinbox. It no longer asks for its text width, and carries the full name as a tooltip in case the column is too narrow.
akenmorris
force-pushed
the
amorris/2640-correspondence-studio
branch
from
August 26, 2026 00:16
2f993c2 to
fc8e467
Compare
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.
This PR adds a Correspondence Quality panel to Studio's Analyze pane, bringing the
existing
correspondence-qualitymetric into the GUI. Each sample is reconstructedfrom its local particles through Studio's own mesh warper and the distance back to
its groomed mesh is shown three ways: as an overlay on the surface and particles, as
a sortable per-sample table, and as a ranked chart. Because the common failure is a
few swapped correspondence points — which barely move the mean while spiking the
tail — the metric also reports the 99th percentile, the chart plots that tail
alongside the ranked metric, and a "Localized (p99 / mean)" sort surfaces those cases
even when their mean looks healthy.
CorrespondenceEvaluationgains an in-memoryentry point shared by the command line and Studio, plus the first tests for it.