Edit on GitHub

starplast.strategy_card

The strategy card: what a strategy answers and how well it works, before any prose.

Selecting a strategy in the Strategies tab shows this card first. It is built to be read in a few seconds and to look the same for every strategy, so two cards can be compared by eye:

header      number and name, the method as a chip, the calibration grade as a coloured badge,
            and one plain line saying what it answers;
four bars   the same four positions on every card (`scorecard.headline`): Better than chance,
            Reach, and the two metrics of the strategy's task a biologist asks about first --
            each with its 95% interval and a tick at its chance level, and a plain sentence on
            hover;
buttons     Run, Test and Details (the Guide, the Settings and the Results tables, one click
            away);
about       four collapsed lines -- what it does, how it is evaluated, what failure looks like,
            what success looks like (`strategy_explainers`) -- each opening to its full text;
examples    one real failure and one real success, side by side as mini scorecards, and what
            the successful run added about genes nobody has labeled.

The bars are painted, not tables, so the eye reads lengths instead of numbers. Colours come from the theme the application is showing, never a literal at a call site.

GRADES = {'reliable': ('success', 'Reliable: across many held-out tests at its default settings, its skill is clearly above zero and it passes most of them.'), 'works when tuned': ('warning', 'Works when tuned: weak at its default settings, reliable at the setting calibration chose (Details, Settings, Use tuned settings).'), 'weak': ('warning', 'Weak: some skill on average, but not enough, or not often enough, to rely on at any setting tested.'), 'no skill': ('error', 'No skill: across its held-out tests it did no better than the same procedure on shuffled data.'), 'untestable': ('fg_dim', "Untestable: too few of its tests could be scored on this organism's table to judge it.")}
VERDICTS = {'PASS': 'success', 'FAIL': 'error', 'INCONCLUSIVE': 'fg_dim', 'NOT RUN': 'fg_dim'}
def colors() -> dict:

The palette of the theme the application is showing now.

class Pill(PyQt6.QtWidgets.QWidget):

A rounded label: filled for a grade or verdict, outlined for a method chip.

Pill( text: str = '', role: str = 'accent', filled: bool = True, tip: str = '', parent=None)
def setText(self, text: str):

Change the label and resize to fit it.

def text(self) -> str:

The label shown.

def sizeHint(self):

Wide enough for the label in the small bold face, plus its rounded ends.

def paintEvent(self, _event):

paintEvent(self, a0: QPaintEvent|None)

class ScoreBar(PyQt6.QtWidgets.QWidget):

One headline bar: plain label and value, a painted bar with its interval and chance tick, and the technical name small underneath. compact drops the technical line (mini cards).

ScoreBar(compact: bool = False, parent=None)
compact
bar: dict
def set_bar(self, bar: dict):

Show one entry of scorecard.headline_bars.

def value_text(self) -> str:

The value as the bar prints it.

def sizeHint(self):

Tall enough for the label line, the bar and (unless compact) the technical name.

def paintEvent(self, _event):

paintEvent(self, a0: QPaintEvent|None)

class Scorecard(PyQt6.QtWidgets.QWidget):

The four headline bars, stacked, in the same positions for every strategy.

Scorecard(compact: bool = False, parent=None)
bars
def set_bars(self, bars: list):

Fill the four bars from scorecard.headline_bars.

class ElidedLabel(PyQt6.QtWidgets.QLabel):

A one-line label that shortens its text with an ellipsis rather than wrapping.

ElidedLabel(text: str = '', parent=None)
def setText(self, text: str):

Keep the whole text; it is shortened only when painted.

def full_text(self) -> str:

The whole text, before eliding.

def paintEvent(self, _event):

paintEvent(self, a0: QPaintEvent|None)

def card_style(base_px: int = 13) -> str:

The card's stylesheet for the theme in force: sizes relative to the body text size.

class AboutBox(PyQt6.QtWidgets.QWidget):

About this test: four fields, each one line until opened.

AboutBox(parent=None)
rows
def set_key(self, key: str):

Show one strategy's four fields, all collapsed.

def expand(self, field: str, on: bool = True):

Open (or close) one field to its full text.

class ExampleCard(PyQt6.QtWidgets.QFrame):

A mini scorecard for one worked example: what was asked, the verdict, four small bars and the one or two sentences saying why it failed or what it found.

ExampleCard(title: str, parent=None)
title
verdict
target
card
text
def paintEvent(self, _event):

paintEvent(self, a0: QPaintEvent|None)

def set_example(self, example: dict, task: str):

Fill from one entry of strategy_examples.json (a failure or a success).

class NewInformation(PyQt6.QtWidgets.QWidget):

What the successful run added: its top calls for genes without a known label.

NewInformation(parent=None)
def gene_clicked(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

lay
title
grid_host
grid
note
buttons: list
def set_new(self, new: dict):

Show up to five rows: gene (a button that finds it on the map), product, call, support.

class StrategyCard(PyQt6.QtWidgets.QWidget):

The default view of one strategy: header, four bars, buttons, about, examples.

StrategyCard(tips: dict | None = None, parent=None)
def run_clicked(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

def test_clicked(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

def details_clicked(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

def gene_clicked(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

name
method
grade
task
question
scorecard
basis
record
mine
mine_verdict
mine_card
run_btn
test_btn
details_btn
about
fails
works
new
def restyle(self) -> bool:

Apply the card stylesheet for the theme and text size in force; True if it changed.

def show_strategy( self, s, organism: str, card: dict, verdict: dict, grade: str, basis: str):

Fill the card for strategy s: card and verdict as headline_bars takes them.

def show_test(self, test):

Put a finished self-test on the card in the same four bars.