instrumentserver.gui.parameter_manager.logic#

Parameter Manager GUI logic that builds no widgets: the Type claims and tint palette, the Lock rows and texts, the Types tab rows, and the PMState cache of Types and Locks.

Module Attributes

GUTTER_COLUMN

Logical index of the gutter column of ModelParameterManager, whose items carry a row's stack of Types for the GutterDelegate to draw.

GUTTER_WIDTH

Fixed pixel width of the gutter column in the view.

GUTTER_ROLE

Data role under which a row's stack of Type names is stored on its gutter item; GutterDelegate reads it to draw the bands.

TINT_PALETTE

tint and tintAlt are the row background of a claimed row (tintAlt for every other sibling row), bar the colour of its gutter band.

TINT_PALETTE_DARK

dark, low-saturation tints that keep the theme's light text readable, and brighter bars so the gutter bands stand out on a dark background.

TINT_COLOURS

The palettes as QColors, in the same slot order.

LOCK_COLUMN

Logical index of the Lock column of ModelParameterManager (plan task 5.3).

LOCK_COLUMN_WIDTH

Fixed default pixel width of the Lock column in the view (the user can resize it: the section is Interactive).

LOCK_COLOUR

the fill of a row's lock button while its Lock is locked.

Functions

also_types(instance, types, parameters)

Every Type the submodule instance is an Instance of (plan task 5.5; the mock's also cell), in types order.

build_lock_rows(locks, types, instrument_name)

The Locks panel's rows from the client-side state (plan task 5.4; the mock's locks-panel walk).

compute_claims(types, parameters)

The mock's claims() ported to the client-side state (plan task 5.2): which Type claims each row of the Parameter Manager tree, and which stack of Types carries it.

followers_reaching(path, locks, instrument_name)

Paths (relative to the Parameter Manager) of every Follower whose locked Lock targets the parameter at path, directly or over a chain of locked Locks.

instances_of_type(type_name, types, parameters)

Paths (relative to the Parameter Manager) of every Instance of the Type type_name, computed client-side over the model's parameter rows (plan task 5.5; the mock's instancesOf): the same candidate rules compute_claims() matches by — every proper dotted prefix, never the root, never anything under Globals — carrying every effective path with the declared unit (D12).

is_dark_theme()

Whether the application currently uses a dark theme: its palette's window colour is darker than its window text.

lock_button_tooltip(locked, target)

The lock/relock button's tooltip for one Lock state (the mock's strings), with target relative to the Parameter Manager.

lock_column_text(path, locks, instrument_name)

The text the Lock column shows for the parameter row path (a path relative to the Parameter Manager), computed client-side over the state's Locks (plan task 5.3; the mock's lock cell).

lock_root(path, locks, instrument_name)

The end of the chain of locked Locks that starts at path (the mock's root): the parameter a locked read at path finally asks.

lock_row_paths(rows)

Every row path of the built rows, depth first.

parse_default_text(text)

The value a default line edit's text stands for: None when the text is empty, otherwise the text parsed with ast.literal_eval, falling back to the raw string when it does not parse.

rank_lock_targets(follower, candidates, claims)

The arm strip's Target candidates in the mock's completer order.

relative_path(full, instrument_name)

The path relative to the Parameter Manager: full with the <instrument_name>. prefix stripped.

tint_colours()

The tint palette for the current theme (is_dark_theme()).

type_entry_rows(type_name, types[, ...])

The entries-pane rows of the Type type_name (plan task 5.5): its effective parameter set as a segment-sorted tree of submodule and entry rows.

Classes

Claim(type, instance, stack)

What the tree shows for one row that Types carry (the mock's claims()): the Claiming Type whose tint the row shows, the Instance submodule path that claims it, and every Type carrying the row, outermost first (the gutter draws one band per Type, up to three).

EntryRow(path, kind[, unit, nested_type, ...])

One row of the Types tab's entries pane (plan task 5.5; the mock's tParamRows): a submodule row of the selected Type's tree, or one entry of it.

LockRow(path, type_locks, lock, children)

One row of the Locks panel (plan task 5.4): a Target of one or more Locks — plain, or the Target of a Type Lock — and the Followers beneath it, recursively for chains.

PMState()

Client-side cache of a Parameter Manager's Types and Locks.

TypePalette()

Assigns the fixed tint palette's slots to the Types the GUI knows.

class instrumentserver.gui.parameter_manager.logic.Claim(type: str, instance: str, stack: List[str])[source]#

Bases: object

What the tree shows for one row that Types carry (the mock’s claims()): the Claiming Type whose tint the row shows, the Instance submodule path that claims it, and every Type carrying the row, outermost first (the gutter draws one band per Type, up to three).

instance: str#
stack: List[str]#
type: str#
class instrumentserver.gui.parameter_manager.logic.EntryRow(path: str, kind: str, unit: str = '', nested_type: str | None = None, own: bool = False, from_type: str | None = None, default: Any = None, target: str | None = None)[source]#

Bases: object

One row of the Types tab’s entries pane (plan task 5.5; the mock’s tParamRows): a submodule row of the selected Type’s tree, or one entry of it.

kind is "submodule" or "entry". A submodule row carries nested_type — the Type required at that submodule, or None for a structural row that only carries the rows below it. An entry row carries the effective entry’s unit and defining Type (from_type), whether the selected Type defines the entry itself (own), its default — an own entry’s stored default, a Nested Type entry’s default as stored on the defining Type — and, own entries only, the target of the entry’s Type Lock relative to the Parameter Manager (None while it has none).

default: Any = None#
from_type: str | None = None#
kind: str#
nested_type: str | None = None#
own: bool = False#
path: str#
target: str | None = None#
unit: str = ''#
instrumentserver.gui.parameter_manager.logic.GUTTER_COLUMN = 3#

Logical index of the gutter column of ModelParameterManager, whose items carry a row’s stack of Types for the GutterDelegate to draw. The existing columns keep their indexes: name (0), unit (1), delegate (2).

instrumentserver.gui.parameter_manager.logic.GUTTER_ROLE = 257#

Data role under which a row’s stack of Type names is stored on its gutter item; GutterDelegate reads it to draw the bands.

instrumentserver.gui.parameter_manager.logic.GUTTER_WIDTH = 12#

Fixed pixel width of the gutter column in the view.

instrumentserver.gui.parameter_manager.logic.LOCK_COLOUR = '#7e5bef'#

the fill of a row’s lock button while its Lock is locked.

Type:

The mock’s one purple (its --log-value token)

instrumentserver.gui.parameter_manager.logic.LOCK_COLUMN = 4#

Logical index of the Lock column of ModelParameterManager (plan task 5.3). The existing columns keep their indexes: name (0), unit (1), delegate (2), gutter (3). The view shows the Lock column between the unit and the delegate column.

instrumentserver.gui.parameter_manager.logic.LOCK_COLUMN_WIDTH = 140#

Fixed default pixel width of the Lock column in the view (the user can resize it: the section is Interactive).

class instrumentserver.gui.parameter_manager.logic.LockRow(path: str, type_locks: List[Tuple[str, str]], lock: PMLockBluePrint | None, children: List[LockRow])[source]#

Bases: object

One row of the Locks panel (plan task 5.4): a Target of one or more Locks — plain, or the Target of a Type Lock — and the Followers beneath it, recursively for chains. type_locks holds every (Type name, entry path) whose Type Lock Target the row is; lock is the row’s own Lock (None for a plain Target).

children: List[LockRow]#
lock: PMLockBluePrint | None#
path: str#
type_locks: List[Tuple[str, str]]#
class instrumentserver.gui.parameter_manager.logic.PMState[source]#

Bases: object

Client-side cache of a Parameter Manager’s Types and Locks.

The Parameter Manager GUI owns one instance (ParameterManagerGui.state) so its widgets can react to Types and Locks without querying the Server again. It starts empty and is filled from the Parameter Manager — a Proxy Instrument or a local one — with refresh(); the pm-lock-update and pm-type-update Broadcasts then keep single entries current through apply_lock() and apply_type() (D22).

types maps each Type’s name to its PMTypeBluePrint; locks maps each Follower’s path relative to the Parameter Manager — the form list_locks() returns — to its PMLockBluePrint.

apply_lock(path: str, lock: PMLockBluePrint | None) → None[source]#

Record the change a pm-lock-update Broadcast reports about the Follower at path.

Parameters:
  • path – the Follower’s path relative to the Parameter Manager.

  • lock – the Follower’s PMLockBluePrint, or None when its Lock was removed (the entry is dropped then).

apply_type(name: str, type_blueprint: PMTypeBluePrint | None) → None[source]#

Record the change a pm-type-update Broadcast reports about the Type name.

Parameters:
  • name – the Type’s name.

  • type_blueprint – the Type’s PMTypeBluePrint, or None when the Type was removed (the entry is dropped then).

locks: Dict[str, PMLockBluePrint]#
refresh(instrument: Any) → None[source]#

Re-read every Type and Lock from the Parameter Manager.

Works with a Proxy Instrument and with a local Parameter Manager: both expose list_types, get_type and list_locks.

Parameters:

instrument – the Parameter Manager whose Types and Locks to read.

types: Dict[str, PMTypeBluePrint]#
instrumentserver.gui.parameter_manager.logic.TINT_COLOURS: List[Dict[str, QColor]] = [{'bar': <PyQt5.QtGui.QColor object>, 'tint': <PyQt5.QtGui.QColor object>, 'tintAlt': <PyQt5.QtGui.QColor object>}, {'bar': <PyQt5.QtGui.QColor object>, 'tint': <PyQt5.QtGui.QColor object>, 'tintAlt': <PyQt5.QtGui.QColor object>}, {'bar': <PyQt5.QtGui.QColor object>, 'tint': <PyQt5.QtGui.QColor object>, 'tintAlt': <PyQt5.QtGui.QColor object>}, {'bar': <PyQt5.QtGui.QColor object>, 'tint': <PyQt5.QtGui.QColor object>, 'tintAlt': <PyQt5.QtGui.QColor object>}, {'bar': <PyQt5.QtGui.QColor object>, 'tint': <PyQt5.QtGui.QColor object>, 'tintAlt': <PyQt5.QtGui.QColor object>}]#

The palettes as QColors, in the same slot order.

instrumentserver.gui.parameter_manager.logic.TINT_PALETTE: List[Dict[str, str]] = [{'bar': '#4a7fc1', 'tint': '#e8f1fb', 'tintAlt': '#dfe9f6'}, {'bar': '#4f9e57', 'tint': '#e9f4e9', 'tintAlt': '#e0ede0'}, {'bar': '#b98a3e', 'tint': '#f6efe4', 'tintAlt': '#efe7db'}, {'bar': '#b5605f', 'tint': '#f9ecec', 'tintAlt': '#f2e3e3'}, {'bar': '#3f9490', 'tint': '#e5f4f2', 'tintAlt': '#dcece9'}]#

tint and tintAlt are the row background of a claimed row (tintAlt for every other sibling row), bar the colour of its gutter band. The slot of a Type is its index in this list.

Type:

The mock’s TINTS for a light theme

instrumentserver.gui.parameter_manager.logic.TINT_PALETTE_DARK: List[Dict[str, str]] = [{'bar': '#5b8fd1', 'tint': '#1e2a3a', 'tintAlt': '#233245'}, {'bar': '#5fae67', 'tint': '#1e2e21', 'tintAlt': '#243627'}, {'bar': '#c99a4e', 'tint': '#33291b', 'tintAlt': '#3b3020'}, {'bar': '#c5706f', 'tint': '#352122', 'tintAlt': '#3e2728'}, {'bar': '#4fa4a0', 'tint': '#1b302e', 'tintAlt': '#213835'}]#

dark, low-saturation tints that keep the theme’s light text readable, and brighter bars so the gutter bands stand out on a dark background.

Type:

The same five hues for a dark theme, slot for slot

class instrumentserver.gui.parameter_manager.logic.TypePalette[source]#

Bases: object

Assigns the fixed tint palette’s slots to the Types the GUI knows.

A Type keeps its slot while it exists: the slot is assigned when the GUI first sees the Type (in PMState.types order after a refresh, then each new Type from a pm-type-update Broadcast), it never changes while the Type is in the state, and it is freed when the Type is removed. A new Type takes the lowest free slot, or slot 0 when all five are used (the mock’s freeTint recycles when exhausted).

bar_colour(type_name: str) → QColor | None[source]#

The gutter band colour of the Type type_name.

colours(type_name: str) → Dict[str, QColor] | None[source]#

The palette entry of the Type type_name (tint, tintAlt and bar) for the current theme, or None when it has no slot.

slots: Dict[str, int]#
sync(type_names: Any) → None[source]#

Free the slots of Types that are gone and assign slots to new ones, in the given creation order.

Parameters:

type_names – the names of the Types the GUI knows (PMState.types).

instrumentserver.gui.parameter_manager.logic.also_types(instance: str, types: Mapping[str, PMTypeBluePrint], parameters: Mapping[str, str]) → List[str][source]#

Every Type the submodule instance is an Instance of (plan task 5.5; the mock’s also cell), in types order. The Types pane shows the ones besides the selected Type as also <t1>, <t2>.

instrumentserver.gui.parameter_manager.logic.build_lock_rows(locks: Mapping[str, PMLockBluePrint], types: Mapping[str, PMTypeBluePrint], instrument_name: str) → List[LockRow][source]#

The Locks panel’s rows from the client-side state (plan task 5.4; the mock’s locks-panel walk).

locks maps each Follower’s path (relative to the Parameter Manager) to its PMLockBluePrint; types maps each Type’s name to its PMTypeBluePrint. An unlocked Lock still remembers its Target (D5), so a Follower’s Lock names its Target whether the Lock is locked or not.

The Targets are the unique Targets of the Locks, in locks order. The roots are the Targets that carry no Lock of their own, the Type Lock Targets first (a stable sort, like the mock’s), each walked recursively into its Followers — a seen set guards against loops — and then any Target the first walk did not reach (the mock’s second pass, e.g. a cycle among Followers). Every row carries its own Lock (None for a plain Target) and its (Type, entry) pairs.

instrumentserver.gui.parameter_manager.logic.compute_claims(types: Mapping[str, PMTypeBluePrint], parameters: Mapping[str, str]) → Dict[str, Claim][source]#

The mock’s claims() ported to the client-side state (plan task 5.2): which Type claims each row of the Parameter Manager tree, and which stack of Types carries it.

Parameters:
  • types – the Parameter Manager’s Types (PMState.types), each as its PMTypeBluePrint.

  • parameters – every parameter row of the tree as {path relative to the Parameter Manager: unit}.

Returns:

for every claimed parameter path and submodule path, its Claim.

Matching mirrors ParameterManager.instances_of (D12) client-side: a candidate is every submodule path derived from the parameter paths (every proper dotted prefix; never the root, never anything under Globals) and it is an Instance when it carries every effective path with the declared unit. The Claiming Type is the innermost (the longest Instance path), then the largest effective set, then the Type name. A Nested Type claims at and below its submodule, so a row it defines is claimed by it, with the outer Types behind it in the stack.

instrumentserver.gui.parameter_manager.logic.followers_reaching(path: str, locks: Mapping[str, PMLockBluePrint], instrument_name: str) → List[str][source]#

Paths (relative to the Parameter Manager) of every Follower whose locked Lock targets the parameter at path, directly or over a chain of locked Locks.

Only locked hops count (D7): an unlocked Lock answers get with its own value, so the Followers behind it do not see an update made past it. The walk follows each hop’s Target and stops there — no infinite loop on a cycle, and every Follower appears once.

instrumentserver.gui.parameter_manager.logic.instances_of_type(type_name: str, types: Mapping[str, PMTypeBluePrint], parameters: Mapping[str, str]) → List[str][source]#

Paths (relative to the Parameter Manager) of every Instance of the Type type_name, computed client-side over the model’s parameter rows (plan task 5.5; the mock’s instancesOf): the same candidate rules compute_claims() matches by — every proper dotted prefix, never the root, never anything under Globals — carrying every effective path with the declared unit (D12). An empty Type has no Instances. The Instances are sorted, for a stable pane order.

instrumentserver.gui.parameter_manager.logic.is_dark_theme() → bool[source]#

Whether the application currently uses a dark theme: its palette’s window colour is darker than its window text. Reading the palette (rather than the platform’s colour scheme) also covers a dark palette or style sheet set on the application itself.

instrumentserver.gui.parameter_manager.logic.lock_button_tooltip(locked: bool, target: str) → str[source]#

The lock/relock button’s tooltip for one Lock state (the mock’s strings), with target relative to the Parameter Manager. Shared by the tree’s per-row widget (plan task 5.3) and the Locks panel (plan task 5.4).

instrumentserver.gui.parameter_manager.logic.lock_column_text(path: str, locks: Mapping[str, PMLockBluePrint], instrument_name: str) → str[source]#

The text the Lock column shows for the parameter row path (a path relative to the Parameter Manager), computed client-side over the state’s Locks (plan task 5.3; the mock’s lock cell).

A Follower shows its own Lock state: locked to <target> while locked, unlocked · <target> (middle dot) while unlocked, with the Target relative to the Parameter Manager. A parameter that is no Follower but the Target of N Locks — locked and unlocked alike, the way ParameterManager.followers_of() counts — shows target ×N (multiplication sign). Every other row shows nothing.

A row that is both Follower and Target shows its Follower text, which wins over the Target note (the mock’s rec.lockedTo || srcNote(p)).

instrumentserver.gui.parameter_manager.logic.lock_root(path: str, locks: Mapping[str, PMLockBluePrint], instrument_name: str) → str[source]#

The end of the chain of locked Locks that starts at path (the mock’s root): the parameter a locked read at path finally asks. Only locked hops count (D7): an unlocked Lock answers get with its own value, so the walk stops there. A seen set guards against a cycle. Paths are relative to the Parameter Manager, except the stored PMLockBluePrint.target, which is relativized on the way.

instrumentserver.gui.parameter_manager.logic.lock_row_paths(rows: List[LockRow]) → List[str][source]#

Every row path of the built rows, depth first.

instrumentserver.gui.parameter_manager.logic.parse_default_text(text: str) → Any[source]#

The value a default line edit’s text stands for: None when the text is empty, otherwise the text parsed with ast.literal_eval, falling back to the raw string when it does not parse.

instrumentserver.gui.parameter_manager.logic.rank_lock_targets(follower: str, candidates: Iterable[str], claims: Mapping[str, Claim], arm_rel: str | None = None) → List[str][source]#

The arm strip’s Target candidates in the mock’s completer order.

arm_rel is the Follower’s path relative to its Instance (the part behind the Claiming Type’s Instance path), or None when the Follower is claimed by no Type; an explicit arm_rel argument overrides it, which the Types tab’s Type Lock re-target (plan task 5.5) uses to rank for a Type’s entry path — there is no claimed Follower and so nothing to exclude. Rank 0: the candidate’s own relative path equals arm_rel (the same leaf on a sibling Instance, the mock’s first pick). Rank 1: .<arm_rel> occurs in the candidate (a submodule on the way). Rank 2: everything else. Equal ranks order alphabetically; the Follower itself is never a candidate. Cycles are not filtered here: the Server refuses them and the arm strip shows its error text.

instrumentserver.gui.parameter_manager.logic.relative_path(full: str, instrument_name: str) → str[source]#

The path relative to the Parameter Manager: full with the <instrument_name>. prefix stripped. PMLockBluePrint.target stores the full dotted path, while model item names and every string the GUI shows the user are relative to the Parameter Manager.

instrumentserver.gui.parameter_manager.logic.tint_colours() → List[Dict[str, QColor]][source]#

The tint palette for the current theme (is_dark_theme()).

instrumentserver.gui.parameter_manager.logic.type_entry_rows(type_name: str, types: Mapping[str, PMTypeBluePrint], instrument_name: str = '') → List[EntryRow][source]#

The entries-pane rows of the Type type_name (plan task 5.5): its effective parameter set as a segment-sorted tree of submodule and entry rows.

The sort is segment-wise like the mock’s (paths order by their dotted segments), so a submodule row sorts directly before the rows below it and the list reads as a tree in order.

An entry the Type defines itself (from_type == type_name) is own: its default and target come from the Type’s own entry, with the stored Type Lock Target relativized with instrument_name. An entry a Nested Type defines shows that Type as from_type and the defining Type’s own default for the path relative to it (the mock’s ownerRel).

Parameters:
  • type_name – the selected Type’s name.

  • types – the Parameter Manager’s Types (PMState.types).

  • instrument_name – the Parameter Manager’s name, for relativizing the stored Type Lock Targets; without it the stored full-form Targets are returned unchanged.

Returns:

the rows, parents before children.