diff --git a/pyproject.toml b/pyproject.toml
index 5914c00..c2b224d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -88,7 +88,6 @@ lint.ignore = [
"D101", # Ignore missing docstring in public classes
"F401",
# FIXME: those are ignored for now, should be fixed eventually
- "E501", # Ignore line too long
"ERA001", # Found commented-out code
"T201", # `print` found"
"SIM105", # Use `contextlib.suppress`
diff --git a/src/petab_gui/commands.py b/src/petab_gui/commands.py
index 9ba472a..6fb97d9 100644
--- a/src/petab_gui/commands.py
+++ b/src/petab_gui/commands.py
@@ -12,8 +12,8 @@ def _convert_dtype_with_nullable_int(series, dtype):
"""Convert a series to the specified dtype, handling nullable integers.
When converting to integer types and the series contains NaN values,
- this function automatically uses pandas nullable integer types (Int64, Int32, etc.)
- instead of numpy integer types which don't support NaN.
+ this function automatically uses pandas nullable integer types (Int64,
+ Int32, etc.) instead of numpy integer types which don't support NaN.
Args:
series: The pandas Series to convert
diff --git a/src/petab_gui/controllers/file_io_controller.py b/src/petab_gui/controllers/file_io_controller.py
index 49032dd..b82fd63 100644
--- a/src/petab_gui/controllers/file_io_controller.py
+++ b/src/petab_gui/controllers/file_io_controller.py
@@ -1,7 +1,7 @@
"""File I/O Controller for PEtab GUI.
-This module contains the FileIOController class, which handles all file input/output
-operations for PEtab models, including:
+This module contains the FileIOController class, which handles all
+file input/output operations for PEtab models, including:
- Opening and saving PEtab YAML files
- Opening and saving COMBINE archives (OMEX)
- Opening and saving individual tables
@@ -35,7 +35,8 @@ class FileIOController:
Attributes
----------
main : MainController
- Reference to the main controller for access to models, views, and other controllers.
+ Reference to the main controller for access to models, views, and
+ other controllers.
model : PEtabModel
The PEtab model being managed.
view : MainWindow
@@ -60,8 +61,9 @@ def __init__(self, main_controller):
def save_model(self):
"""Save the entire PEtab model.
- Opens a dialog to select the save format and location, then saves the model
- as either a COMBINE archive (OMEX), ZIP file, or folder structure.
+ Opens a dialog to select the save format and location, then saves
+ the model as either a COMBINE archive (OMEX), ZIP file, or folder
+ structure.
Returns
-------
@@ -129,7 +131,8 @@ def save_single_table(self):
Returns
-------
bool or None
- True if saved successfully, False if cancelled, None if no active table.
+ True if saved successfully, False if cancelled, None if no
+ active table.
"""
active_controller = self.main.active_controller()
if not active_controller:
@@ -253,8 +256,9 @@ def _open_file(self, actionable, file_path, sep, mode):
Parameters
----------
actionable : str
- Type of file: "yaml", "omex", "sbml", "measurement", "observable",
- "parameter", "condition", "visualization", "simulation", "data_matrix".
+ Type of file: "yaml", "omex", "sbml", "measurement",
+ "observable", "parameter", "condition", "visualization",
+ "simulation", "data_matrix".
file_path : str
Path to the file.
sep : str
@@ -412,7 +416,8 @@ def _load_file_list(self, controller, file_list, file_type, yaml_dir):
file_mode = "overwrite" if i == 0 else "append"
controller.open_table(yaml_dir / file_name, mode=file_mode)
self.logger.log_message(
- f"Loaded {file_type} file ({i + 1}/{len(file_list)}): {file_name}",
+ f"Loaded {file_type} file ({i + 1}/{len(file_list)}): "
+ f"{file_name}",
color="blue",
)
@@ -478,8 +483,8 @@ def open_yaml_and_load_files(self, yaml_path=None, mode="overwrite"):
)
if not all_exist:
error_msg = (
- "The following files referenced in the YAML are missing:\n - "
- + "\n - ".join(missing_files)
+ "The following files referenced in the YAML are "
+ "missing:\n - " + "\n - ".join(missing_files)
)
self.logger.log_message(error_msg, color="red")
QMessageBox.critical(self.view, "Missing Files", error_msg)
@@ -565,7 +570,10 @@ def open_yaml_and_load_files(self, yaml_path=None, mode="overwrite"):
self.main.unsaved_changes_change(False)
except FileNotFoundError as e:
- error_msg = f"File not found: {e.filename if hasattr(e, 'filename') else str(e)}"
+ error_msg = (
+ f"File not found: "
+ f"{e.filename if hasattr(e, 'filename') else str(e)}"
+ )
self.logger.log_message(error_msg, color="red")
QMessageBox.warning(self.view, "File Not Found", error_msg)
except KeyError as e:
@@ -659,12 +667,14 @@ def load_example(self, example_name):
Parameters
----------
example_name : str
- Name of the example subdirectory (e.g., "Boehm", "Simple_Conversion").
+ Name of the example subdirectory (e.g., "Boehm",
+ "Simple_Conversion").
Notes
-----
Finds and loads the example dataset from the package directory.
- No internet connection required - the example is bundled with the package.
+ No internet connection required - the example is bundled with the
+ package.
"""
try:
# Use importlib.resources to access packaged example files
@@ -687,7 +697,10 @@ def load_example(self, example_name):
with as_file(yaml_file) as yaml_path:
if not yaml_path.exists():
- error_msg = f"Example '{example_name}' not found or problem.yaml file is missing."
+ error_msg = (
+ f"Example '{example_name}' not found or "
+ f"problem.yaml file is missing."
+ )
self.logger.log_message(error_msg, color="red")
QMessageBox.warning(
self.view, "Example Invalid", error_msg
diff --git a/src/petab_gui/controllers/mother_controller.py b/src/petab_gui/controllers/mother_controller.py
index 31a6da9..ce2eb69 100644
--- a/src/petab_gui/controllers/mother_controller.py
+++ b/src/petab_gui/controllers/mother_controller.py
@@ -728,7 +728,8 @@ def replace(self):
self.view.toggle_replace()
def _toggle_whats_this_mode(self, on: bool):
- """Enable/disable click-to-help mode by installing/removing the global filter.
+ """
+ Enable/disable click-to-help mode.
On enter: show a short instruction bubble.
"""
@@ -754,7 +755,7 @@ def _toggle_whats_this_mode(self, on: bool):
self._show_help_welcome()
def _show_help_welcome(self):
- """Centered welcome with a 'Don't show again' option persisted in QSettings."""
+ """Welcome with a 'Don't show again' option persisted in QSettings."""
settings = settings_manager.settings
if settings.value("help_mode/welcome_disabled", False, type=bool):
return
@@ -765,9 +766,12 @@ def _show_help_welcome(self):
msg.setText(
"Welcome to help mode
"
"
"
- "- Click any widget, tab, or column header to see its help.
"
- "- Click the same item again or press Esc to close the bubble.
"
- "- Press Esc with no bubble, or toggle the ? button, to exit.
"
+ "- Click any widget, tab, or column header to see its "
+ "help.
"
+ "- Click the same item again or press Esc to close "
+ "the bubble.
"
+ "- Press Esc with no bubble, or toggle the ? "
+ "button, to exit.
"
"
"
)
dont = QCheckBox("Don't show again")
@@ -795,7 +799,7 @@ def about(self):
)
def _show_next_steps_panel(self):
- """Show the next steps panel (ignores 'don't show again' preference)."""
+ """Show the next steps panel."""
# Sync checkbox state with current settings
dont_show = settings_manager.get_value(
"next_steps/dont_show_again", False, bool
diff --git a/src/petab_gui/controllers/plot_coordinator.py b/src/petab_gui/controllers/plot_coordinator.py
index 9bf01d5..073fdbf 100644
--- a/src/petab_gui/controllers/plot_coordinator.py
+++ b/src/petab_gui/controllers/plot_coordinator.py
@@ -23,7 +23,8 @@ class PlotCoordinator:
Attributes
----------
main : MainController
- Reference to the main controller for access to models, views, and other controllers.
+ Reference to the main controller for access to models, views, and
+ other controllers.
model : PEtabModel
The PEtab model being visualized.
view : MainWindow
@@ -188,7 +189,8 @@ def _on_plot_point_clicked(self, x, y, label, data_type):
x : float
X-coordinate of the clicked point (time).
y : float
- Y-coordinate of the clicked point (measurement or simulation value).
+ Y-coordinate of the clicked point (measurement or simulation
+ value).
label : str
Label of the clicked point (observable ID).
data_type : str
@@ -250,7 +252,8 @@ def column_index(name):
and self._floats_match(row_y, y)
):
# Manually update highlight BEFORE selecting row
- # This ensures the circle appears even though we skip the signal handler
+ # This ensures the circle appears even though we skip
+ # the signal handler
if data_type == "measurement":
self.plotter.highlight_from_selection([row])
else:
@@ -272,7 +275,8 @@ def column_index(name):
# Provide feedback if no match found
if not matched:
self.logger.log_message(
- f"No matching row found for plot point (obs={obs}, x={x:.4g}, y={y:.4g})",
+ f"No matching row found for plot point "
+ f"(obs={obs}, x={x:.4g}, y={y:.4g})",
color="orange",
)
diff --git a/src/petab_gui/controllers/simulation_controller.py b/src/petab_gui/controllers/simulation_controller.py
index 24b6652..3ef9a4d 100644
--- a/src/petab_gui/controllers/simulation_controller.py
+++ b/src/petab_gui/controllers/simulation_controller.py
@@ -22,7 +22,8 @@ class SimulationController:
Attributes
----------
main : MainController
- Reference to the main controller for access to models, views, and other controllers.
+ Reference to the main controller for access to models, views, and
+ other controllers.
model : PEtabModel
The PEtab model being simulated.
logger : LoggerController
@@ -80,7 +81,7 @@ def simulate(self):
value = sbml_model.get_parameter_value(param_id)
nominal_values.append(value)
except Exception:
- # If parameter not found in SBML, use default value of 1
+ # If parameter not found in SBML, use default value
nominal_values.append(1.0)
# Add nominalValue column to parameter_df
@@ -108,7 +109,8 @@ def simulate(self):
# report current basico / COPASI version
self.logger.log_message(
- f"Simulate with basico: {basico.__version__}, COPASI: {basico.COPASI.__version__}",
+ f"Simulate with basico: {basico.__version__}, "
+ f"COPASI: {basico.COPASI.__version__}",
color="green",
)
diff --git a/src/petab_gui/controllers/table_controllers.py b/src/petab_gui/controllers/table_controllers.py
index b51dc32..52bf16b 100644
--- a/src/petab_gui/controllers/table_controllers.py
+++ b/src/petab_gui/controllers/table_controllers.py
@@ -227,8 +227,9 @@ def append_df(self, new_df: pd.DataFrame):
self.model.beginResetModel()
current_df = self.model.get_df()
- # For tables without a named index (measurement, visualization, simulation),
- # ignore the index to avoid removing appended data due to index conflicts
+ # For tables without a named index (measurement, visualization,
+ # simulation), ignore the index to avoid removing appended data due
+ # to index conflicts
if self.model.table_type in [
"measurement",
"visualization",
@@ -238,7 +239,8 @@ def append_df(self, new_df: pd.DataFrame):
[current_df, new_df], axis=0, ignore_index=True
)
else:
- # For tables with named indices, concatenate and remove duplicate indices
+ # For tables with named indices, concatenate and remove
+ # duplicate indices
combined_df = pd.concat([current_df, new_df], axis=0)
combined_df = combined_df[
~combined_df.index.duplicated(keep="first")
@@ -784,12 +786,14 @@ def _detect_time_column(self, df) -> str | None:
return None
def _rank_dose_candidates(self, df: pd.DataFrame) -> list[str]:
- """Rank DataFrame columns by likelihood of containing dose/concentration data.
+ """Rank columns by likelihood of containing dose/concentration data.
- This method implements a lightweight scoring system to identify and rank
- columns that are most likely to contain dose, concentration, or drug-related
- data. The ranking is based on multiple heuristics including column naming
- patterns, data types, value ranges, and statistical properties.
+ This method implements a lightweight scoring system to identify
+ and rank columns that are most likely to contain dose,
+ concentration, or drug-related
+ data. The ranking is based on multiple heuristics including column
+ naming patterns, data types, value ranges, and statistical
+ properties.
Parameters
----------
@@ -800,29 +804,32 @@ def _rank_dose_candidates(self, df: pd.DataFrame) -> list[str]:
Returns
-------
list[str]
- Column names sorted by descending likelihood of containing dose data.
- Columns with higher scores appear first. In case of tied scores,
- columns with fewer unique values are ranked higher.
+ Column names sorted by descending likelihood of containing
+ dose data. Columns with higher scores appear first. In case of
+ tied scores, columns with fewer unique values are ranked higher.
Notes
-----
The scoring algorithm considers the following criteria:
- - **Name matching** (+2.0 points): Column names containing keywords like
- 'dose', 'conc', 'concentration', 'drug', 'compound', 'stim', 'input',
- or patterns like 'u' (case-insensitive).
+ - **Name matching** (+2.0 points): Column names containing keywords
+ like 'dose', 'conc', 'concentration', 'drug', 'compound', 'stim',
+ 'input', or patterns like 'u' (case-insensitive).
- - **Numeric data type** (+1.0 points): Columns with integer or float dtype.
+ - **Numeric data type** (+1.0 points): Columns with integer or float
+ dtype.
- - **Reasonable cardinality** (+0.8 points): Columns with 2-30 unique
- non-null values, which is typical for dose series.
+ - **Reasonable cardinality** (+0.8 points): Columns with 2-30
+ unique non-null values, which is typical for dose series.
- - **Non-negative values** (+0.3 points): All values are >= 0 when converted
- to numeric (dose/concentration values are typically non-negative).
+ - **Non-negative values** (+0.3 points): All values are >= 0 when
+ converted to numeric (dose/concentration values are typically
+ non-negative).
- - **Monotonic tendency** (+0.2 points): At least 70% of consecutive numeric
- differences are non-decreasing, indicating potential dose escalation
- patterns. Requires at least 5 non-null numeric values.
+ - **Monotonic tendency** (+0.2 points): At least 70% of
+ consecutive numeric differences are non-decreasing, indicating
+ potential dose escalation patterns. Requires at least 5 non-null
+ numeric values.
Raises
------
diff --git a/src/petab_gui/controllers/utils.py b/src/petab_gui/controllers/utils.py
index 3af5af8..f8ef706 100644
--- a/src/petab_gui/controllers/utils.py
+++ b/src/petab_gui/controllers/utils.py
@@ -29,9 +29,12 @@ class _WhatsThisClickHelp(QObject):
While the action is checked:
• Left-click shows a What's This bubble for the target under cursor.
- • Clicking the SAME target again closes the bubble (stays in help mode).
- • ESC closes the bubble if one is open; if none is open, exits help mode.
- • Special cases: QTabBar tabs and QHeaderView sections handled explicitly.
+ • Clicking the SAME target again closes the bubble (stays in help
+ mode).
+ • ESC closes the bubble if one is open; if none is open, exits help
+ mode.
+ • Special cases: QTabBar tabs and QHeaderView sections handled
+ explicitly.
"""
def __init__(self, action):
@@ -81,7 +84,8 @@ def eventFilter(self, _obj, ev):
if isinstance(w, QScrollBar):
return False
- # If click landed outside app widgets (e.g., on the bubble), just close it
+ # If click landed outside app widgets (e.g., on the bubble),
+ # just close it
if not w:
self._has_bubble = False
return True
diff --git a/src/petab_gui/controllers/validation_controller.py b/src/petab_gui/controllers/validation_controller.py
index 550cd13..712d4af 100644
--- a/src/petab_gui/controllers/validation_controller.py
+++ b/src/petab_gui/controllers/validation_controller.py
@@ -23,7 +23,8 @@ class ValidationController:
Attributes
----------
main : MainController
- Reference to the main controller for access to models, views, and other controllers.
+ Reference to the main controller for access to models, views, and
+ other controllers.
model : PEtabModel
The PEtab model being validated.
logger : LoggerController
diff --git a/src/petab_gui/models/tooltips.py b/src/petab_gui/models/tooltips.py
index 3cb2ff6..00dac90 100644
--- a/src/petab_gui/models/tooltips.py
+++ b/src/petab_gui/models/tooltips.py
@@ -24,23 +24,32 @@ def register_tips(
"measurement",
header={
"observableId": "ID from Observables; the output being measured.",
- "preequilibrationConditionId": "Condition for preequilibration; empty = none.",
+ "preequilibrationConditionId": (
+ "Condition for preequilibration; empty = none."
+ ),
"simulationConditionId": "Condition ID used for simulation.",
"time": "Time in SBML units; number or 'inf' (steady state).",
- "measurement": "Measured value; same units/scale as model output.",
- "observableParameters": "Override placeholder params; ';'-separated values/names; empty if none.",
- "noiseParameters": "Std dev σ as value or name; NaN if σ is modeled.",
+ "measurement": ("Measured value; same units/scale as model output."),
+ "observableParameters": (
+ "Override placeholder params; ';'-separated values/names; "
+ "empty if none."
+ ),
+ "noiseParameters": (
+ "Std dev σ as value or name; NaN if σ is modeled."
+ ),
"datasetId": "Dataset grouping ID (for plotting).",
"replicateId": "Replicate label within datasetId.",
},
cell={
"observableId": "Must exist in Observables.",
- "preequilibrationConditionId": "Condition ID or empty for no preeq.",
+ "preequilibrationConditionId": ("Condition ID or empty for no preeq."),
"simulationConditionId": "Condition ID from Conditions.",
"time": "e.g. 0, 5, 10 or 'inf' for steady state.",
"measurement": "Numeric observed value.",
- "observableParameters": "Match placeholders; provide n ';'-separated values/names.",
- "noiseParameters": "Sigma value or parameter name; NaN if modeled.",
+ "observableParameters": (
+ "Match placeholders; provide n ';'-separated values/names."
+ ),
+ "noiseParameters": ("Sigma value or parameter name; NaN if modeled."),
"datasetId": "Optional dataset ID to group points.",
"replicateId": "Optional replicate tag within dataset.",
},
@@ -50,20 +59,47 @@ def register_tips(
register_tips(
"observable",
header={
- "observableId": "Unique ID; letters, digits, underscores; not starting with digit. Referenced in Measurements.",
- "observableName": "Optional display name; not used for identification.",
- "observableFormula": "Observation function as text formula. May use SBML symbols or parameters from parameter table. Can introduce placeholder parameters observableParameter{n}_{observableId}.",
- "observableTransformation": "Transformation applied in objective; one of lin, log, log10. Default: lin.",
- "noiseFormula": "Noise model formula or numeric σ. May include noiseParameter{n}_{observableId}. Must be overridden in Measurement table if present.",
- "noiseDistribution": "Noise distribution type: normal (σ) or laplace (scale). Default: normal.",
+ "observableId": (
+ "Unique ID; letters, digits, underscores; not starting with "
+ "digit. Referenced in Measurements."
+ ),
+ "observableName": (
+ "Optional display name; not used for identification."
+ ),
+ "observableFormula": (
+ "Observation function as text formula. May use SBML symbols "
+ "or parameters from parameter table. Can introduce placeholder "
+ "parameters observableParameter{n}_{observableId}."
+ ),
+ "observableTransformation": (
+ "Transformation applied in objective; one of lin, log, log10. "
+ "Default: lin."
+ ),
+ "noiseFormula": (
+ "Noise model formula or numeric σ. May include "
+ "noiseParameter{n}_{observableId}. Must be overridden in "
+ "Measurement table if present."
+ ),
+ "noiseDistribution": (
+ "Noise distribution type: normal (σ) or laplace (scale). "
+ "Default: normal."
+ ),
},
cell={
- "observableId": "Identifier; must be valid and unique. Used in Measurement table.",
+ "observableId": (
+ "Identifier; must be valid and unique. Used in Measurement table."
+ ),
"observableName": "Optional label for output/plots.",
- "observableFormula": "E.g. a species ID, assignment rule, or formula with parameters.",
+ "observableFormula": (
+ "E.g. a species ID, assignment rule, or formula with parameters."
+ ),
"observableTransformation": "Choose: lin, log, or log10.",
- "noiseFormula": "Numeric σ or formula with noiseParameter{n}_{observableId}.",
- "noiseDistribution": "normal (σ as std dev) or laplace (σ as scale).",
+ "noiseFormula": (
+ "Numeric σ or formula with noiseParameter{n}_{observableId}."
+ ),
+ "noiseDistribution": (
+ "normal (σ as std dev) or laplace (σ as scale)."
+ ),
},
)
@@ -71,30 +107,52 @@ def register_tips(
register_tips(
"parameter",
header={
- "parameterId": "Unique ID; must match SBML parameter, condition override, or observable/noise parameter.",
- "parameterName": "Optional label for plotting; may differ from SBML name.",
+ "parameterId": (
+ "Unique ID; must match SBML parameter, condition override, "
+ "or observable/noise parameter."
+ ),
+ "parameterName": (
+ "Optional label for plotting; may differ from SBML name."
+ ),
"parameterScale": "Scale for estimation: lin, log, or log10.",
- "lowerBound": "Lower bound (linear space). Optional if estimate==0.",
- "upperBound": "Upper bound (linear space). Optional if estimate==0.",
- "nominalValue": "Value if not estimated (estimate==0). Linear space.",
+ "lowerBound": ("Lower bound (linear space). Optional if estimate==0."),
+ "upperBound": ("Upper bound (linear space). Optional if estimate==0."),
+ "nominalValue": (
+ "Value if not estimated (estimate==0). Linear space."
+ ),
"estimate": "1 = estimated, 0 = fixed.",
- "initializationPriorType": "Prior for sampling initial points. Default: parameterScaleUniform.",
- "initializationPriorParameters": "Parameters for initialization prior; ';'-separated; numeric.",
- "objectivePriorType": "Prior type used in objective function.",
- "objectivePriorParameters": "Parameters for objective prior; ';'-separated; numeric.",
+ "initializationPriorType": (
+ "Prior for sampling initial points. Default: "
+ "parameterScaleUniform."
+ ),
+ "initializationPriorParameters": (
+ "Parameters for initialization prior; ';'-separated; numeric."
+ ),
+ "objectivePriorType": ("Prior type used in objective function."),
+ "objectivePriorParameters": (
+ "Parameters for objective prior; ';'-separated; numeric."
+ ),
},
cell={
- "parameterId": "Must match SBML/condition/observable/noise parameter ID.",
+ "parameterId": (
+ "Must match SBML/condition/observable/noise parameter ID."
+ ),
"parameterName": "Optional descriptive name.",
"parameterScale": "Choose lin, log, or log10.",
"lowerBound": "Numeric lower bound (linear space).",
"upperBound": "Numeric upper bound (linear space).",
"nominalValue": "Numeric value if not estimated.",
"estimate": "0 = fixed, 1 = estimated.",
- "initializationPriorType": "E.g., uniform, normal, laplace, logNormal, parameterScaleUniform…",
- "initializationPriorParameters": "Numeric parameters for init prior; e.g., mean;stddev.",
- "objectivePriorType": "Prior type for optimization objective.",
- "objectivePriorParameters": "Numeric parameters for objective prior.",
+ "initializationPriorType": (
+ "E.g., uniform, normal, laplace, logNormal, parameterScaleUniform…"
+ ),
+ "initializationPriorParameters": (
+ "Numeric parameters for init prior; e.g., mean;stddev."
+ ),
+ "objectivePriorType": ("Prior type for optimization objective."),
+ "objectivePriorParameters": (
+ "Numeric parameters for objective prior."
+ ),
},
)
@@ -102,16 +160,24 @@ def register_tips(
register_tips(
"condition",
header={
- "conditionId": "Unique ID; letters/digits/underscores; not starting with digit. Referenced by Measurements.",
- "conditionName": "Optional human-readable name for reports/plots.",
- "*": "User-defined column. Needs to be SBML ID column: parameter, species, or compartment.",
+ "conditionId": (
+ "Unique ID; letters/digits/underscores; not starting with "
+ "digit. Referenced by Measurements."
+ ),
+ "conditionName": ("Optional human-readable name for reports/plots."),
+ "*": (
+ "User-defined column. Needs to be SBML ID column: parameter, "
+ "species, or compartment."
+ ),
},
cell={
"conditionId": "Enter a valid, unique identifier.",
"conditionName": "Optional label.",
- "*": "User-defined column. Provide numeric value or SBML/parameter ID. "
- "Species IDs = initial amount/concentration (NaN = keep preeq/initial). "
- "Compartment IDs = initial size.",
+ "*": (
+ "User-defined column. Provide numeric value or SBML/parameter "
+ "ID. Species IDs = initial amount/concentration (NaN = keep "
+ "preeq/initial). Compartment IDs = initial size."
+ ),
},
)
@@ -120,13 +186,22 @@ def register_tips(
header={
"plotId": "Plot ID; datasets with same ID share axes.",
"plotName": "Optional plot display name.",
- "plotTypeSimulation": "LinePlot | BarPlot | ScatterPlot. Default: LinePlot.",
- "plotTypeData": "MeanAndSD | MeanAndSEM | replicate | provided. Default: MeanAndSD.",
- "datasetId": "Dataset grouping ID from Measurements (optional).",
- "xValues": "Independent variable: 'time' (default) or parameter/state ID.",
+ "plotTypeSimulation": (
+ "LinePlot | BarPlot | ScatterPlot. Default: LinePlot."
+ ),
+ "plotTypeData": (
+ "MeanAndSD | MeanAndSEM | replicate | provided. "
+ "Default: MeanAndSD."
+ ),
+ "datasetId": ("Dataset grouping ID from Measurements (optional)."),
+ "xValues": (
+ "Independent variable: 'time' (default) or parameter/state ID."
+ ),
"xOffset": "Offset added to x values (default 0).",
"xLabel": "X-axis label; defaults to xValues.",
- "xScale": "lin | log | log10 | order (only with LinePlot). Default: lin.",
+ "xScale": (
+ "lin | log | log10 | order (only with LinePlot). Default: lin."
+ ),
"yValues": "Observable ID to plot on Y.",
"yOffset": "Offset added to y values (default 0).",
"yLabel": "Y-axis label; defaults to yValues.",
@@ -136,8 +211,10 @@ def register_tips(
cell={
"plotId": "Required; same ID -> same axes.",
"plotName": "Optional human-readable name.",
- "plotTypeSimulation": "Choose: LinePlot, BarPlot, or ScatterPlot.",
- "plotTypeData": "Choose: MeanAndSD, MeanAndSEM, replicate, or provided.",
+ "plotTypeSimulation": ("Choose: LinePlot, BarPlot, or ScatterPlot."),
+ "plotTypeData": (
+ "Choose: MeanAndSD, MeanAndSEM, replicate, or provided."
+ ),
"datasetId": "Optional dataset ID to include in this plot.",
"xValues": "Use 'time' or a parameter/state ID.",
"xOffset": "Numeric x offset (e.g., 0).",
@@ -210,8 +287,8 @@ def cell_tip(table: str, column: str) -> str:
COND_TABLE_TOOLTIP = (
"Condition table
"
"• Define condition IDs and names.
"
- "• User-defined SBML ID columns override parameters/species initial "
- "states (NaN keeps preeq/initial)."
+ "• User-defined SBML ID columns override parameters/species "
+ "initial states (NaN keeps preeq/initial)."
)
VIS_TABLE_TOOLTIP = (
@@ -239,14 +316,15 @@ def cell_tip(table: str, column: str) -> str:
DATA_TABLES_TAB_TOOLTIP = (
"Data Tables
"
- "• Edit PEtab tables: Measurement, Observable, Parameter, Condition,"
- " Visualization.
"
- "• Hover headers for definitions;"
- " use toolbar to add/remove rows and import/export."
+ "• Edit PEtab tables: Measurement, Observable, Parameter, "
+ "Condition, Visualization.
"
+ "• Hover headers for definitions; use toolbar to add/remove rows "
+ "and import/export."
)
SBML_MODEL_TAB_TOOLTIP = (
"SBML Model
"
"• Edit SBML (XML) and Antimony side-by-side.
"
- "• Use Forward Changes buttons to sync; see logger for errors."
+ "• Use Forward Changes buttons to sync; see logger for "
+ "errors."
)
diff --git a/src/petab_gui/resources/whats_this.py b/src/petab_gui/resources/whats_this.py
index 4a5d7ee..7c03f59 100644
--- a/src/petab_gui/resources/whats_this.py
+++ b/src/petab_gui/resources/whats_this.py
@@ -5,19 +5,25 @@
"data_tables": (
"Data Tables
"
""
- "- Edit PEtab tables: Measurement, Observable, Parameter, Condition, Visualization.
"
- "- Hover headers for definitions; right-click for context actions.
"
- "- Keep IDs consistent across tables (e.g.,
observableId, condition IDs). "
- "- Import/export to manage files; validation highlights issues.
"
+ "- Edit PEtab tables: Measurement, Observable, Parameter, "
+ "Condition, Visualization.
"
+ "- Hover headers for definitions; right-click for context "
+ "actions.
"
+ "- Keep IDs consistent across tables (e.g., "
+ "
observableId, condition IDs). "
+ "- Import/export to manage files; validation highlights "
+ "issues.
"
"
"
),
"sbml_model": (
"SBML Model
"
""
"- Edit SBML (XML) and Antimony side-by-side.
"
- "- Use the Forward Changes buttons to convert/sync between views.
"
+ "- Use the Forward Changes buttons to convert/sync "
+ "between views.
"
"- Errors and warnings appear in the logger panel below.
"
- "- Some constructs may not round-trip perfectly; keep the canonical SBML copy.
"
+ "- Some constructs may not round-trip perfectly; keep the "
+ "canonical SBML copy.
"
"
"
),
},
@@ -25,7 +31,8 @@
"sbml_editor": (
"SBML editor (XML)
"
""
- "- Paste or edit valid SBML (L2/L3); keep namespaces intact.
"
+ "- Paste or edit valid SBML (L2/L3); keep namespaces "
+ "intact.
"
"- Click Forward → Antimony to generate Antimony.
"
"- Prefer this pane for full SBML feature coverage.
"
"- Conversion issues are reported in the logger.
"
@@ -46,67 +53,87 @@
"table": (
"Measurement table
"
""
- "- Each row is a data point with time, value, and linked IDs.
"
- "observableId must exist in Observable; "
+ "- Each row is a data point with time, value, and linked "
+ "IDs.
"
+ "observableId must exist in "
+ "Observable; "
"condition IDs must exist in Condition. "
"- Use
'inf' for steady-state times. "
- "- Override placeholders
observableParameter{n}_{observableId} "
- "and noise parameters noiseParameter{n}_{observableId} when defined. "
+ "- Override placeholders "
+ "
observableParameter{n}_{observableId} "
+ "and noise parameters "
+ "noiseParameter{n}_{observableId} when "
+ "defined. "
"
"
),
"columns": {
"observableId": (
""
- "- Reference to an observable defined in the Observable table.
"
- "- Must match an existing
observableId. "
+ "- Reference to an observable defined in the Observable "
+ "table.
"
+ "- Must match an existing "
+ "
observableId. "
"
"
),
"preequilibrationConditionId": (
""
- "- Condition used for pre-equilibration; empty = none.
"
+ "- Condition used for pre-equilibration; empty = "
+ "none.
"
"- Must be a valid condition ID if provided.
"
"
"
),
"simulationConditionId": (
""
- "- Condition used for simulation parameters (required).
"
+ "- Condition used for simulation parameters "
+ "(required).
"
"- Must be a valid condition ID.
"
"
"
),
"time": (
""
- "- Numeric time in SBML units, or
'inf' for steady state. "
- "- Use a consistent unit system across data and model.
"
+ "- Numeric time in SBML units, or
'inf' "
+ "for steady state. "
+ "- Use a consistent unit system across data and "
+ "model.
"
"
"
),
"measurement": (
""
- "- Observed numeric value in the same scale/units as the model output.
"
- "- Leave blank for missing values if supported by your workflow.
"
+ "- Observed numeric value in the same scale/units as "
+ "the model output.
"
+ "- Leave blank for missing values if supported by your "
+ "workflow.
"
"
"
),
"observableParameters": (
""
- "- Overrides for placeholders defined in the observable formula.
"
- "- Provide
n semicolon-separated values/names for "
- "observableParameter{n}_{observableId}; empty if none. "
+ "- Overrides for placeholders defined in the observable "
+ "formula.
"
+ "- Provide
n semicolon-separated "
+ "values/names for "
+ "observableParameter{n}_{observableId}; "
+ "empty if none. "
"
"
),
"noiseParameters": (
""
- "- Noise std-dev (or parameter names);
NaN if σ is a model parameter. "
- "- Same rules as
observableParameters for lists and naming. "
+ "- Noise std-dev (or parameter names); "
+ "
NaN if σ is a model parameter. "
+ "- Same rules as
observableParameters for "
+ "lists and naming. "
"
"
),
"datasetId": (
""
- "- Grouping key for plotting (datasets share style/axes).
"
+ "- Grouping key for plotting (datasets share "
+ "style/axes).
"
"- Optional; defaults to per-row if omitted.
"
"
"
),
"replicateId": (
""
- "- Label to distinguish replicates within a dataset.
"
+ "- Label to distinguish replicates within a "
+ "dataset.
"
"- Enables error bars/replicate plotting modes.
"
"
"
),
@@ -116,8 +143,10 @@
"table": (
"Simulation table
"
""
- "- Holds simulated outputs aligned to measurement definitions.
"
- "- Same IDs as Measurement (observable/conditions/time) for comparison.
"
+ "- Holds simulated outputs aligned to measurement "
+ "definitions.
"
+ "- Same IDs as Measurement (observable/conditions/time) for "
+ "comparison.
"
"- Populated by simulator/export; typically read-only.
"
"
"
),
@@ -125,55 +154,66 @@
"observableId": (
""
"- Observable whose simulation is reported.
"
- "- Must match an
observableId in Observable. "
+ "- Must match an
observableId in "
+ "Observable. "
"
"
),
"preequilibrationConditionId": (
""
- "- Preequilibration condition used during simulation; empty = none.
"
+ "- Preequilibration condition used during simulation; "
+ "empty = none.
"
"- Must be a valid condition ID if set.
"
"
"
),
"simulationConditionId": (
""
- "- Condition used to set simulation parameters (required).
"
+ "- Condition used to set simulation parameters "
+ "(required).
"
"- Must be a valid condition ID.
"
"
"
),
"time": (
""
- "- Time point for the simulated value (numeric or
'inf'). "
+ "- Time point for the simulated value (numeric or "
+ "
'inf'). "
"- Use same units as the model.
"
"
"
),
"simulation": (
""
- "- Simulated numeric value (same scale/units as measurement).
"
+ "- Simulated numeric value (same scale/units as "
+ "measurement).
"
"- Used for plotting and residuals.
"
"
"
),
"observableParameters": (
""
- "- Parameters used to evaluate observable placeholders, if applicable.
"
- "- Semicolon-separated values/names; mirrors Measurement rules.
"
+ "- Parameters used to evaluate observable placeholders, "
+ "if applicable.
"
+ "- Semicolon-separated values/names; mirrors "
+ "Measurement rules.
"
"
"
),
"noiseParameters": (
""
- "- Noise parameters applied for simulation/plotting modes.
"
+ "- Noise parameters applied for simulation/plotting "
+ "modes.
"
"- Numeric values or names; may be empty.
"
"
"
),
"datasetId": (
""
"- Dataset grouping to match plotted series.
"
- "- Optional; align with Measurement for overlays.
"
+ "- Optional; align with Measurement for "
+ "overlays.
"
"
"
),
"replicateId": (
""
- "- Replicate label, if simulations are per-replicate.
"
- "- Usually empty unless replicates are simulated explicitly.
"
+ "- Replicate label, if simulations are "
+ "per-replicate.
"
+ "- Usually empty unless replicates are simulated "
+ "explicitly.
"
"
"
),
},
@@ -182,17 +222,22 @@
"table": (
"Observable table
"
""
- "- Defines how model states/expressions map to measured outputs.
"
- "- May introduce placeholders
observableParameter{n}_{observableId} "
+ " - Defines how model states/expressions map to measured "
+ "outputs.
"
+ "- May introduce placeholders "
+ "
observableParameter{n}_{observableId} "
"that are overridden per-measurement. "
- "- Noise model can be numeric σ or a formula; distribution optional.
"
+ "- Noise model can be numeric σ or a formula; distribution "
+ "optional.
"
"
"
),
"columns": {
"observableId": (
""
- "- Unique identifier (letters/digits/underscores; not starting with a digit).
"
- "- Referenced by
measurement.observableId. "
+ "- Unique identifier (letters/digits/underscores; not "
+ "starting with a digit).
"
+ "- Referenced by "
+ "
measurement.observableId. "
"
"
),
"observableName": (
@@ -203,27 +248,36 @@
),
"observableFormula": (
""
- "- Expression using SBML symbols/parameters (e.g., species ID).
"
- "- May define
observableParameter{n}_{observableId} placeholders. "
+ "- Expression using SBML symbols/parameters (e.g., "
+ "species ID).
"
+ "- May define "
+ "
observableParameter{n}_{observableId} "
+ "placeholders. "
"
"
),
"observableTransformation": (
""
- "- Transformation for objective:
lin, log, or log10. "
- "- Defaults to
lin; data and outputs assumed linear if not set. "
+ "- Transformation for objective:
lin, "
+ "log, or log10. "
+ "- Defaults to
lin; data and outputs "
+ "assumed linear if not set. "
"
"
),
"noiseFormula": (
""
- "- Numeric σ (implies normal) or formula for complex noise.
"
- "- May include
noiseParameter{n}_{observableId}; "
+ " - Numeric σ (implies normal) or formula for complex "
+ "noise.
"
+ "- May include "
+ "
noiseParameter{n}_{observableId}; "
"values provided in Measurement. "
"
"
),
"noiseDistribution": (
""
- "normal (σ = std dev) or laplace (σ = scale). "
- "- Log-variants via
observableTransformation = log/log10. "
+ "normal (σ = std dev) or "
+ "laplace (σ = scale). "
+ "- Log-variants via "
+ "
observableTransformation = log/log10. "
"
"
),
},
@@ -232,15 +286,18 @@
"table": (
"Parameter table
"
""
- "- Declares parameters, estimation flag, and bounds (linear space).
"
- "parameterId must match SBML or overrides used elsewhere. "
+ "- Declares parameters, estimation flag, and bounds (linear "
+ "space).
"
+ "parameterId must match SBML or overrides "
+ "used elsewhere. "
"- Optional priors for initialization and/or objective.
"
"
"
),
"columns": {
"parameterId": (
""
- "- Must match an SBML parameter, a condition override, or names used in measurements.
"
+ "- Must match an SBML parameter, a condition override, "
+ "or names used in measurements.
"
"- Unique within this table.
"
"
"
),
@@ -252,8 +309,10 @@
),
"parameterScale": (
""
- "- Estimation scale:
lin, log, or log10. "
- "- Affects optimization scaling, not storage format.
"
+ "- Estimation scale:
lin, "
+ "log, or log10. "
+ "- Affects optimization scaling, not storage "
+ "format.
"
"
"
),
"lowerBound": (
@@ -270,38 +329,46 @@
),
"nominalValue": (
""
- "- Value used when fixed (
estimate==0), in linear space. "
+ "- Value used when fixed (
estimate==0), in "
+ "linear space. "
"- Optional otherwise.
"
"
"
),
"estimate": (
""
- "1 = estimated; 0 = fixed to nominal value. "
+ "1 = estimated; 0 = fixed "
+ "to nominal value. "
"- Controls inclusion in the optimization vector.
"
"
"
),
"initializationPriorType": (
""
- "- Prior for initial point sampling (e.g.,
uniform, normal, "
+ " - Prior for initial point sampling (e.g., "
+ "
uniform, normal, "
"parameterScaleUniform). "
- "- Defaults to
parameterScaleUniform. "
+ "- Defaults to "
+ "
parameterScaleUniform. "
"
"
),
"initializationPriorParameters": (
""
- "- Semicolon-separated numeric parameters; default
lowerBound;upperBound. "
- "- Linear scale unless using parameter-scale priors.
"
+ "- Semicolon-separated numeric parameters; default "
+ "
lowerBound;upperBound. "
+ "- Linear scale unless using parameter-scale "
+ "priors.
"
"
"
),
"objectivePriorType": (
""
- "- Prior contributing to the objective; same options as initialization prior.
"
+ "- Prior contributing to the objective; same options as "
+ "initialization prior.
"
"- Optional; omit for unregularized fits.
"
"
"
),
"objectivePriorParameters": (
""
- "- Semicolon-separated numeric parameters; see initialization prior for formats.
"
+ "- Semicolon-separated numeric parameters; see "
+ "initialization prior for formats.
"
"- Scale rules mirror the chosen prior type.
"
"
"
),
@@ -311,15 +378,18 @@
"table": (
"Condition table
"
""
- "- Defines simulation/experimental conditions referenced by other tables.
"
- "- User-defined columns must be SBML IDs (parameter/species/compartment).
"
+ "- Defines simulation/experimental conditions referenced by "
+ "other tables.
"
+ "- User-defined columns must be SBML IDs "
+ "(parameter/species/compartment).
"
"- Species values act as initial conditions;
"
"
"
),
"columns": {
"conditionId": (
""
- "- Unique identifier (letters/digits/underscores; not starting with a digit).
"
+ "- Unique identifier (letters/digits/underscores; not "
+ "starting with a digit).
"
"- Referenced by Measurement and Simulation.
"
"
"
),
@@ -331,9 +401,12 @@
),
"*": (
""
- "- User-defined column. Must be an SBML ID: parameter, species, or compartment.
"
- "- Numbers or IDs allowed; species = initial amount/concentration "
- "(
NaN keeps preeq/initial), compartments = initial size. "
+ "- User-defined column. Must be an SBML ID: parameter, "
+ "species, or compartment.
"
+ "- Numbers or IDs allowed; species = initial "
+ "amount/concentration "
+ "(
NaN keeps preeq/initial), compartments = "
+ "initial size. "
"
"
),
},
@@ -342,15 +415,19 @@
"table": (
"Visualization table
"
""
- "- Groups datasets into plots and configures axes/scales.
"
- "plotId collects series into the same axes. "
- "- Choose simulation/data types; set labels and offsets.
"
+ "- Groups datasets into plots and configures "
+ "axes/scales.
"
+ "plotId collects series into the same "
+ "axes. "
+ "- Choose simulation/data types; set labels and "
+ "offsets.
"
"
"
),
"columns": {
"plotId": (
""
- "- Plot grouping key; identical IDs share the same axes.
"
+ "- Plot grouping key; identical IDs share the same "
+ "axes.
"
"- Required for multi-series plots.
"
"
"
),
@@ -362,25 +439,29 @@
),
"plotTypeSimulation": (
""
- "LinePlot | BarPlot | ScatterPlot. "
+ "LinePlot | BarPlot | "
+ "ScatterPlot. "
"- Default is
LinePlot. "
"
"
),
"plotTypeData": (
""
- "MeanAndSD | MeanAndSEM | replicate | provided. "
+ "MeanAndSD | MeanAndSEM | "
+ "replicate | provided. "
"- Default is
MeanAndSD. "
"
"
),
"datasetId": (
""
- "- Includes datasets (from Measurement) in this plot.
"
+ "- Includes datasets (from Measurement) in this "
+ "plot.
"
"- Optional; multiple IDs → multiple series.
"
"
"
),
"xValues": (
""
- "- Independent variable:
time (default) or parameter/state ID. "
+ "- Independent variable:
time (default) or "
+ "parameter/state ID. "
"- Values appear as x-axis ticks.
"
"
"
),
@@ -392,20 +473,25 @@
),
"xLabel": (
""
- "- Custom x-axis label; defaults to
xValues. "
+ "- Custom x-axis label; defaults to "
+ "
xValues. "
"- Use units where helpful.
"
"
"
),
"xScale": (
""
- "lin | log | log10 | order (LinePlot only). "
- "- Default is
lin; order places points equidistantly. "
+ "lin | log | "
+ "log10 | order (LinePlot "
+ "only). "
+ "- Default is
lin; order "
+ "places points equidistantly. "
"
"
),
"yValues": (
""
"- Observable ID to plot on the y-axis.
"
- "- Must match
measurement.observableId for overlays. "
+ "- Must match
measurement.observableId for "
+ "overlays. "
"
"
),
"yOffset": (
@@ -416,13 +502,15 @@
),
"yLabel": (
""
- "- Custom y-axis label; defaults to
yValues. "
+ "- Custom y-axis label; defaults to "
+ "
yValues. "
"- Include units where applicable.
"
"
"
),
"yScale": (
""
- "lin | log | log10. "
+ "lin | log | "
+ "log10. "
"- Default is
lin. "
"
"
),
diff --git a/src/petab_gui/settings/settings_model.py b/src/petab_gui/settings/settings_model.py
index 4bbca05..f91400c 100644
--- a/src/petab_gui/settings/settings_model.py
+++ b/src/petab_gui/settings/settings_model.py
@@ -23,7 +23,8 @@ class SettingsModel(QObject):
settings_changed : Signal
Emitted when a setting is updated (passes the key as string).
new_log_message : Signal
- Emitted when a log message should be displayed (passes message and color).
+ Emitted when a log message should be displayed (passes message
+ and color).
"""
settings_changed = Signal(str) # Signal emitted when a setting is updated
diff --git a/src/petab_gui/utils.py b/src/petab_gui/utils.py
index aae0b08..77d2ccb 100644
--- a/src/petab_gui/utils.py
+++ b/src/petab_gui/utils.py
@@ -258,7 +258,8 @@ def process_file(filepath, logger):
petab.C.CONDITION_ID in header
or f"\ufeff{petab.C.CONDITION_ID}" in header
):
- # For condition files with single column, use tab as default separator
+ # For condition files with single column, use tab as default
+ # separator
return "condition", separator if separator is not None else "\t"
if petab.C.PLOT_ID in header:
return "visualization", separator
diff --git a/src/petab_gui/views/dialogs.py b/src/petab_gui/views/dialogs.py
index 1db3e6e..566b773 100644
--- a/src/petab_gui/views/dialogs.py
+++ b/src/petab_gui/views/dialogs.py
@@ -97,8 +97,8 @@ def get_inputs(self):
Returns:
dict: A dictionary containing:
- 'simulationConditionId': The simulation condition ID
- - 'preequilibrationConditionId': The preequilibration condition ID
- (only included if provided)
+ - 'preequilibrationConditionId': The preequilibration
+ condition ID (only included if provided)
"""
inputs = {}
inputs["simulationConditionId"] = self.sim_input.text()
@@ -203,7 +203,8 @@ def __init__(self, parent=None):
# Description
desc = QLabel(
- "This parameter estimation problem can now be used in the following tools:"
+ "This parameter estimation problem can now be used in the "
+ "following tools:"
)
desc.setWordWrap(True)
main_layout.addWidget(desc)
diff --git a/src/petab_gui/views/main_view.py b/src/petab_gui/views/main_view.py
index d672ccf..50dd289 100644
--- a/src/petab_gui/views/main_view.py
+++ b/src/petab_gui/views/main_view.py
@@ -126,7 +126,8 @@ def __init__(self):
self.tab_widget.currentChanged.connect(self.set_docks_visible)
- # Track if we're in a minimize/restore cycle (must be set before load_ui_settings)
+ # Track if we're in a minimize/restore cycle (must be set before
+ # load_ui_settings)
self._was_minimized = False
settings_manager.load_ui_settings(self)
@@ -233,7 +234,7 @@ def add_menu_action(self, dock_widget, name):
def save_dock_visibility(self, visible):
"""Save the visibility status of a QDockWidget when it changes."""
- # Don't save visibility when window is minimized - Qt hides docks automatically
+ # Don't save visibility when window is minimized - Qt hides docks
if self.isMinimized():
return
# if current tab is not the data tab return
diff --git a/src/petab_gui/views/simple_plot_view.py b/src/petab_gui/views/simple_plot_view.py
index bac7e89..0255600 100644
--- a/src/petab_gui/views/simple_plot_view.py
+++ b/src/petab_gui/views/simple_plot_view.py
@@ -35,7 +35,7 @@ def __init__(self, vis_df, cond_df, meas_df, sim_df, group_by):
self.signals = PlotWorkerSignals()
def run(self):
- # Move all Matplotlib plotting to the GUI thread. Only prepare payload here.
+ # Move all Matplotlib plotting to the GUI thread. Only prepare payload.
sim_df = self.sim_df if not self.sim_df.empty else None
payload = {
"vis_df": self.vis_df,
@@ -300,8 +300,9 @@ def _update_tabs(self, fig: plt.Figure):
)
# Map subplot to observable IDs
- # When grouped by condition/dataset, one subplot can have multiple observables
- # Extract all observable IDs from legend labels
+ # When grouped by condition/dataset, one subplot can have
+ # multiple observables. Extract all observable IDs from legend
+ # labels
subplot_title = (
ax.get_title() if ax.get_title() else f"subplot_{idx}"
)
@@ -313,7 +314,8 @@ def _update_tabs(self, fig: plt.Figure):
label_parts = legend_label.split()
if len(label_parts) == 0:
continue
- # Extract observable ID (last part before "simulation" if present)
+ # Extract observable ID (last part before "simulation"
+ # if present)
if label_parts[-1] == "simulation":
obs_id = (
label_parts[-2]
@@ -434,7 +436,8 @@ def __init__(self):
self.highlight_scatters = defaultdict(
list
) # (subplot index) → scatter artist
- self.point_index_map = {} # (subplot index, observableId, x, y) → row index
+ # (subplot index, observableId, x, y) → row index
+ self.point_index_map = {}
self.click_callback = None
def clear_highlight(self):
@@ -480,7 +483,8 @@ def _on_pick(self, event):
for handle, lbl in zip(handles, labels, strict=False):
if handle is artist:
# Extract observable ID and data type from legend label
- # Format can be: "observableId", "datasetId observableId", or "datasetId observableId simulation"
+ # Format can be: "observableId", "datasetId observableId",
+ # or "datasetId observableId simulation"
label_parts = lbl.split()
if len(label_parts) == 0:
continue
@@ -495,7 +499,8 @@ def _on_pick(self, event):
)
else:
data_type = "measurement"
- # Label is last: "dataset obs" -> "obs" or just "obs" -> "obs"
+ # Label is last: "dataset obs" -> "obs" or just
+ # "obs" -> "obs"
label = label_parts[-1]
break
diff --git a/tests/test_upload.py b/tests/test_upload.py
index 8d9422e..688ff61 100644
--- a/tests/test_upload.py
+++ b/tests/test_upload.py
@@ -448,7 +448,7 @@ def tearDown(self):
self.view.deleteLater()
def test_single_file_yaml_backward_compatibility(self):
- """Test that single-file YAML loading still works (backward compatibility)."""
+ """Test that single-file YAML loading still works."""
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
@@ -501,6 +501,7 @@ def test_single_file_yaml_backward_compatibility(self):
def test_multi_file_yaml_loading(self):
"""Test loading YAML with multiple files per category."""
+ contr = self.controller.measurement_controller
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
@@ -558,21 +559,15 @@ def test_multi_file_yaml_loading(self):
# Call the method
self.controller.open_yaml_and_load_files(str(yaml_file))
- # Verify measurement files were loaded (once in overwrite, once in append)
- self.assertEqual(
- self.controller.measurement_controller.open_table.call_count, 2
- )
+ # Verify measurement files loading (once in overwrite/append)
+ self.assertEqual(contr.open_table.call_count, 2)
# Check that first call was with mode='overwrite'
- first_call = self.controller.measurement_controller.open_table.call_args_list[
- 0
- ]
+ first_call = contr.open_table.call_args_list[0]
self.assertEqual(first_call[1].get("mode"), "overwrite")
# Check that second call was with mode='append'
- second_call = self.controller.measurement_controller.open_table.call_args_list[
- 1
- ]
+ second_call = contr.open_table.call_args_list[1]
self.assertEqual(second_call[1].get("mode"), "append")
# Verify observable files were loaded