Config labels in every output, independent facet scales, green CI - #3
Merged
Conversation
The two-choice substrate plot was the last output still ignoring the configured labels: its legend hardcoded "left" / "right", so `metadata.substrates` never reached it. It now names each side after the substrate that side holds, falling back to left/right when the experiment records no labels, or the same label on both sides — where the side is the only thing telling the two boxes apart. Same figure was also ordering conditions alphabetically while every other figure uses the experiment sequence; it now shares ordered_condition_labels(), which additionally learns to group by the order column itself so an unlabelled experiment (grouping on the numeric code) no longer trips over a duplicate column. Documents how metadata.conditions / metadata.substrates apply positionally to the channel map and flow into every table and figure, versus the plot-only plotting.condition_labels rename, and records the unreleased changes since v0.1.0.
Faceted figures shared one y-axis, so a substrate the flies barely touched collapsed onto the baseline next to one they fed on heavily — the sucrose panel was unreadable. Facets now scale independently and stack top-to-bottom, with the shared condition axis drawn once under the bottom facet. plotting.facet_share_y restores the single shared scale (magnitudes comparable across facets, at the cost of the smaller one) and plotting.facet_layout: columns the side-by-side arrangement. Fixes the significance brackets, which the independent scaling exposed: the stack was laid out in axes fractions computed *before* the y-limit was grown to fit it, so with 5 conditions (10 brackets) it overshot 1.0 — drawing over the facet title — while squashing the data into the lower third. The layout is now solved in final fractions and the step compresses to a bounded band, so the brackets stay inside the axes and the data always keeps at least half the height. Brackets on independent axes anchor to their own facet's data rather than the tallest, which would otherwise re-inflate the axis the independent scaling was meant to keep tight.
CI has been red since 2026-07-30: it syncs with `uv sync --frozen`, which installs the `dev` group but not the optional `gui` one, so every Qt accessor degrades to Any and reading a value back out of a widget trips warn_return_any. Locally PySide6 is installed, the accessors are typed, and mypy is silent — which is why this only ever showed up on the runner. The flypad.gui.* override already exists to make the layer check identically with or without the extra; warn_return_any was the one setting missing from it. Verified by reproducing the runner's environment (UV_PROJECT_ENVIRONMENT with `uv sync --frozen`): ruff, ruff format, mypy and pytest all pass there now (227 passed, test_gui skipped for the absent qtpy).
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 #2.
Config labels set in
experiment.yamlreachedconfig.used.yamlbut not the exportedtables or the figures. The bulk of that was already fixed in a39a78d (on
mainsince2026-07-29, after the issue was filed against 2778288); this branch finishes the job,
takes care of a readability problem the fix exposed, and gets CI green again.
Name the substrates in the two-choice figure (9fc8fd6)
substrate_comparison()was the last output ignoring the configured labels: its legendhardcoded
left/right, sometadata.substratesnever reached it. Each side is nownamed after the substrate it holds, falling back to
left/rightwhen the experimentrecords no labels — or the same label on both sides, where the side is the only thing
telling the two boxes apart.
The same figure ordered conditions alphabetically while every other figure uses the
experiment sequence; it now shares
ordered_condition_labels(), which additionallylearns to group by the order column itself so an unlabelled experiment (grouping on the
numeric code) no longer trips over a duplicate column.
Stack facets and scale each to its own data (894dd6c)
Faceted figures shared one y-axis, so a substrate the flies barely touched collapsed onto
the baseline beside one they fed on heavily. Facets now scale independently and stack
top-to-bottom, with the shared condition axis drawn once under the bottom facet.
Two new options restore the old behaviour:
plotting.facet_share_y: truefor a singleshared scale (magnitudes comparable across facets, at the cost of the smaller one), and
plotting.facet_layout: columnsfor the side-by-side arrangement.This exposed a latent bug in the significance brackets, fixed here: the stack was laid
out in axes fractions computed before the y-limit was grown to fit it, so with 5
conditions (10 brackets) it overshot 1.0 — drawing over the facet title — while squashing
the data into the lower third. The layout is now solved in final fractions and the step
compresses into a bounded band, so brackets stay inside the axes and the data always
keeps at least half the height. On independent axes brackets anchor to their own facet's
data rather than the tallest, which would otherwise re-inflate the axis the independent
scaling was meant to keep tight.
Type-check the GUI layer without the gui extra (12135c7)
CI has been red since 2026-07-30, unrelated to the above. It syncs with
uv sync --frozen, which installs thedevgroup but not the optionalguione, soevery Qt accessor degrades to
Anyand reading a value back out of a widget tripswarn_return_any. Locally PySide6 is installed, the accessors are typed, and mypy issilent — which is why this only ever showed up on the runner. The
flypad.gui.*overridealready exists to make the layer check identically with or without the extra;
warn_return_anywas the one setting missing from it.Verification
End-to-end on the shipped
data/sample/20240215fixture:The configured names appear in
per_fly/events/per_condition/comparisons(CSV and Parquet), the box-plot tick labels, the facet titles, the substrate-figure
legend, and the raster and time-course legends.
guiextra installed).UV_PROJECT_ENVIRONMENT+uv sync --frozen):ruff, ruff format, mypy and pytest all pass — 227 passed,
test_guiskipped for theabsent qtpy.
layout / independent scaling, the x-axis being captioned once, and the bracket stack
staying inside the axes.
Docs
docs/configuration.mdgains a section on howmetadata.conditions/.substratesapplypositionally and which outputs they reach, versus the figure-only
plotting.condition_labelsrename, plus a table for the two new faceting options.CHANGELOG.mdgains an[Unreleased]section.