ProteinView

class ProteinView()

Bases: MetaSubsetTabView

Subclass of MetaSubsetTabView for estimating translocating protein size and shape from nanopore blockage events.

Given pore diameter/length, fits a two-population (prolate/oblate) volume-and-shape-factor model via Monte Carlo rejection sampling, either per event (Individual mode) or across the aggregate distribution (Ensemble mode). Also supports subset filtering, per-event trace/histogram inspection, and committing or reporting fit results.

Public Methods

ProteinView.confirm_fit_commit(loader: str, table_name: str | None) → None

Ask the user about an overwrite if there is one, then send the write out.

Phase two of the commit. table_name is both the answer and the flag: None means the database holds no fit columns, so there is nothing to confirm and the write goes straight out. The user’s decision travels back in the intent rather than being parked on this widget between the halves.

Parameters:
  • loader (str) – Name or ID of the database loader plugin.

  • table_name (Optional[str]) – the table already holding fit columns, or None

Returns:

None

Return type:

None

ProteinView.get_current_view() → str

Abstract method to get the name of the current view.

Subclasses must override this to return the current view name.

Returns:

The name of the view currently displayed.

Return type:

str

Raises:

NotImplementedError – Always, unless overridden by a subclass.

ProteinView.get_walkthrough_steps() → List[Tuple[str, str, str, Callable[[], QWidget | List[QWidget]]]]

Abstract method to retrieve the walkthrough steps for the current view.

Subclasses must override this to return a list of walkthrough steps, each a (title, description, view name, widget getter) tuple.

Returns:

The ordered walkthrough steps for this view.

Return type:

List[WalkthroughStep]

Raises:

NotImplementedError – Always, unless overridden by a subclass.

ProteinView.handle_parameter_change(submodel_name: str, action_name: str, args: tuple) → None

Handle changes triggered by UI controls such as updates to axis selection or filters.

Parameters:
  • submodel_name (str) – Name of the submodel that triggered the action.

  • action_name (str) – Name of the action triggered.

  • args (tuple) – Tuple containing action-specific arguments.

ProteinView.notify_plugin_state_changed(metaclass: str, plugin_key: str, reason: str) → None

Ignore plugin state changes: nothing this tab shows depends on them.

The one change the app announces is a database loader gaining columns, and this tab reads no column names. The experiment tree is fetched when the loader is selected.

Parameters:
  • metaclass (str) – The metaclass of the plugin instance whose state changed.

  • plugin_key (str) – The unique key identifying the plugin instance that changed.

  • reason (str) – A short string identifying what kind of change occurred.

Returns:

None

Return type:

None

ProteinView.on_fit_commit_finished(loader: str) → None

Tell the rest of the app that the loader has new columns.

Called by the Controller once the write has been attempted, so a commit that never reached the database does not announce new columns. This tab reads no column names itself, so it asks for none.

Parameters:

loader (str) – Name or ID of the database loader plugin.

Returns:

None

Return type:

None

ProteinView.set_distribution_fits(df_prolate: DataFrame, df_oblate: DataFrame, fit_data: DataFrame) → None

Plot the geometries every fitted event is consistent with.

The answering half of distribution_fits_requested. The sampling is done by ProteinModel.sample_event_geometries(), because a Monte Carlo over a forward model is not drawing and its output is written back to the database as this tab’s fit columns.

Parameters:
  • df_prolate (pd.DataFrame) – every fitted event’s prolate solutions, pooled

  • df_oblate (pd.DataFrame) – every fitted event’s oblate solutions, pooled

  • fit_data (pd.DataFrame) – one summary row per fitted event, keyed by its database id

Returns:

None

Return type:

None

ProteinView.set_ensemble_geometry_fit(popt: ndarray[tuple[int, ...], dtype[float64]], curve: ndarray[tuple[int, ...], dtype[float64]], plot_data: DataFrame, plot_type: str, df_prolate: DataFrame, df_oblate: DataFrame) → None

Draw the fitted ensemble and the geometries it is consistent with.

The answering half of ensemble_fit_requested. The fitted curve arrives already evaluated at the bins it was fitted on, which is what lets the model function live on ProteinModel. The sampled solutions arrive with it, since they are drawn from that same fit.

An ensemble that sampled nothing still reaches here, and still draws the fit: the Controller reports the bail-out, and the two empty frames simply skip their scatterplots. Refusing to call this at all would have taken the fitted curve off the screen with them.

Parameters:
  • popt (npt.NDArray[np.float64]) – the fit parameters

  • curve (npt.NDArray[np.float64]) – the fitted curve evaluated at the histogram’s bins

  • plot_data (pd.DataFrame) – the aggregated histogram DataFrame that was fitted

  • plot_type (str) – the plot type label to reuse when plotting the fit

  • df_prolate (pd.DataFrame) – the prolate solutions, empty if none were sampled

  • df_oblate (pd.DataFrame) – the oblate solutions, empty if none were sampled

Returns:

None

Return type:

None

ProteinView.set_ensemble_histogram(plot_data: DataFrame, plot_type: str, bins: Any, sizes: bool, dataset_label: str, dataset_key: Tuple[Any, ...], d: float, L: float, N: int) → None

Draw the averaged histogram, then ask for the geometry it implies.

The answering half of ensemble_histogram_requested. The averaging is done by ProteinModel.build_all_points_histogram(), because walking a subset’s events and binning every sample of them is aggregation rather than drawing, and the result is exported with the plot.

The bookkeeping happens here rather than back in the request half because set_ensemble_geometry_fit reads allowed_bins and allowed_sizes, so they have to describe this plot before the fit is asked for.

Parameters:
  • plot_data (pd.DataFrame) – the averaged histogram, as bin centers and amplitudes

  • plot_type (str) – ‘Raw Histogram’ or ‘Filtered Histogram’

  • bins (Any) – the bin request this histogram was built to

  • sizes (bool) – did bins refer to a bin width (True) or a count (False)

  • dataset_label (str) – the label the histogram is drawn under

  • dataset_key (Tuple[Any, ...]) – the plotted-datasets key for this subset

  • d (float) – the diameter of the pore in nanometers

  • L (float) – the length of the pore in nanometers

  • N (int) – target number of samples to draw for each ensemble

Returns:

None

Return type:

None

ProteinView.set_event_histogram_fits(fits: Sequence[Tuple[ndarray[tuple[int, ...], dtype[float64]] | None, ndarray[tuple[int, ...], dtype[float64]] | None]], histograms: Sequence[Tuple[ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]]] | None], event_data: Sequence[Dict[str, Any]]) → None

Draw one subplot per event, overlaying each fit that succeeded.

The answering half of event_histogram_fits_requested. Every list is index-aligned with event_data, so the subplot grid keeps its original positions whether or not a given event produced a histogram or a fit.

A fit that failed is simply not overlaid - the histogram is still drawn. That was previously expressed as a ValueError raised into a bare except in the same loop body; it is a plain branch now, because the fit no longer happens here and there is nothing left to catch.

Parameters:
  • fits (Sequence[Tuple[Optional[npt.NDArray[np.float64]], Optional[npt.NDArray[np.float64]]]]) – one (fit parameters, fitted curve) pair per event, index-aligned with event_data

  • histograms (Sequence[Optional[Tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]]]) – each event’s (bin centers, amplitude) pair, or None where none could be built

  • event_data (Sequence[Dict[str, Any]]) – List of event dictionaries, each containing data and metadata for one event.

Returns:

None

Return type:

None

ProteinView.set_xyerr_scatterplot(columns: Sequence[ndarray[tuple[int, ...], dtype[float64]]], ax: Axes, axis_labels: Sequence[str], dataset_label: str) → None

Draw a scatterplot of two filtered columns with their error bars.

The answering half of xyerr_scatterplot_requested. Separate from set_scatterplot because only this tab has an error-bar variant. The four arrays arrive filtered together, so the bars still line up with the points after any row is dropped.

Parameters:
  • columns (Sequence[npt.NDArray[np.float64]]) – the filtered x, y, x error and y error values

  • ax (Axes) – the axis object on which to plot

  • axis_labels (Sequence[str]) – the x and y axis labels, already formatted

  • dataset_label (str) – Label for the dataset.

Returns:

None

Return type:

None

ProteinView.update_available_plugins(available_plugins: Dict[str, List[str]]) → None

Called whenever a new plugin is instantiated elsewhere in the app, to keep an up-to-date list of possible data sources for use by this plugin.

Parameters:

available_plugins (Dict[str, List[str]]) – dict of lists keyed by MetaClass, listing the identifiers of all instantiated plugins throughout the app.

ProteinView.update_plot(plot_type: str, data: DataFrame, cols: Sequence[str], units: Sequence[str | None], logscales: Sequence[bool], dataset_label: str = '', bins: Any = None, sizes: bool = False, err_cols: Sequence[str] | None = None) → None

update the plot area

Private Methods

ProteinView._init() → None

Initialize the ProteinView instance.

ProteinView._reset_actions(axis_type: str = '2d') → None

Clears the figure and reinitializes axes. This will also add a flag to the tab action history if @register_action is being used to keep track of actions. Only actions applied after the most recent call to this function will be recreated if the related file is loaded.

Also clears stored fit state for whichever analysis mode is currently active (self.fit_data for Individual, self.ensemble_fit_* for Ensemble), leaving the other mode’s fit untouched. This means switching modes and running Update Plot, or clicking Reset, only affects the fit belonging to the mode you’re currently in.

Parameters:

axis_type (str) – Either ‘2d’ or ‘3d’ to determine plot projection.

Returns:

None

Return type:

None

Properties

ProteinView._subset_controls

The controls panel, under the name MetaSubsetTabView’s shared methods use.

Annotated with the base’s type rather than ProteinControls so the override matches the declaration verbatim, which is what the plugin compliance test compares. Tab-specific code keeps using self.proteincontrols.

Returns:

the panel built by _build_controls

Return type:

MetaSubsetTabControls

ProteinView.ax_hist
ProteinView.ax_vm
ProteinView.canvas_hist
ProteinView.canvas_vm
ProteinView.fig_hist
ProteinView.fig_vm