From faa6776f29bf37cf34da9a41744ab394c9c78985 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 19:06:01 +0000 Subject: [PATCH 1/5] Template: models are documented in AGENTS.md, no PID model example shipped The four kinds of models of the extensions are described in a new section of AGENTS.md, which points to the working examples of pymodaq_plugins_mockexamples. The PID model template, whose main() opened an experiment file that is not shipped, is removed and the models flag comment is no longer about PID only. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg --- AGENTS.md | 25 ++++- pyproject.toml | 2 +- .../models/PIDModelTemplate.py | 100 ------------------ .../models/__init__.py | 6 -- 4 files changed, 25 insertions(+), 108 deletions(-) delete mode 100644 src/pymodaq_plugins_template/models/PIDModelTemplate.py delete mode 100644 src/pymodaq_plugins_template/models/__init__.py diff --git a/AGENTS.md b/AGENTS.md index f0e82c3..6a441f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,9 @@ Prefer the first option that fits: instruments** (data viewer, analysis, h5 browsing, configuration tools). 4. A plain script, for a one-off sequence that does not need a GUI. +A **model** (section 6) is not a separate option: it tailors an existing extension (PID, optimizers, data mixer, +sequencer) to your experiment. + ## 2. Workflow ```bash @@ -167,7 +170,27 @@ and the deprecated `CustomApp` / `CustomExt` hooks `setup_docks` and `setup_menu Only when no instrument is needed. Same (non-deprecated) lifecycle as above, `parent` is a `DockArea` or `QMainWindow`, and `main()` creates the app with `mkQApp`. If instruments become necessary, move the logic to a `CustomExt`. -## 6. Done checklist +## 6. Models of the extensions (`models/`) + +Four Dashboard extensions delegate the part that depends on your experiment to a model class that your package +provides: PID (`PIDModelGeneric`), Bayesian and Adaptive optimizers (`OptimizerModelGeneric` or `OptimizerModelDefault`), +DataMixer (`DataMixerModel`) and the Sequencer (`ChoiceModelBase`). Write a model, not an extension, when one of these +extensions already does the job and only the conversion of the measurements or of the outputs is specific. + +- Set `models = true` in `[features]`; entry points are generated only then (`pymodaq.models`). +- Create the `models/` folder at the root of the package, one model per module; the module name is the name shown in + the extension. The model is the class defined in the module that derives from the base class of the extension (it may + derive from your own intermediate class; PID and DataMixer only accepted a direct subclass of the generic base + before the release that follows 5.3.3, so derive directly from it if you must support older releases). +- The template ships no model on purpose. Start from the working examples of + [`pymodaq_plugins_mockexamples`](https://github.com/PyMoDAQ/pymodaq_plugins_mockexamples) (`PIDModelBeamSteering`, + `PIDModelMockHeater`, `BayesianModelMock`, `DataMixerModelFit`) and from the page "Models of the extensions" of the + PyMoDAQ documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and + detectors of that package. +- Do not use the old `pid_models` flag nor the word "preset" in new code: a model script that opens the Dashboard loads + an experiment file. + +## 7. Done checklist - [ ] Names (package, files, classes) match and the `template` placeholders are gone. - [ ] The `[features]` flags at the top of `pyproject.toml` match the folders you use (`instruments`, `extensions`, diff --git a/pyproject.toml b/pyproject.toml index b30c619..c5c381e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [features] # defines the plugin features contained into this plugin instruments = true # true if plugin contains instrument classes (else false, notice the lowercase for toml files) extensions = false # true if plugins contains dashboard extensions -models = false # true if plugins contains pid models +models = false # true if plugins contains models of the extensions (PID, optimizers, data mixer, sequencer) h5exporters = false # true if plugin contains custom h5 file exporters scanners = false # true if plugin contains custom scan layout (daq_scan extensions) diff --git a/src/pymodaq_plugins_template/models/PIDModelTemplate.py b/src/pymodaq_plugins_template/models/PIDModelTemplate.py deleted file mode 100644 index 2b2dce8..0000000 --- a/src/pymodaq_plugins_template/models/PIDModelTemplate.py +++ /dev/null @@ -1,100 +0,0 @@ -import numpy as np - -from pymodaq.extensions.pid.utils import PIDModelGeneric, DataToActuatorPID, main -from pymodaq_data.data import DataToExport, DataCalculated - -from pymodaq.utils.data import DataActuator - -from typing import List - - -def some_function_to_convert_the_pid_outputs(outputs: List[float], dt: float, stab=True): - """ Should be replaced here or in the model class to process the outputs """ - return outputs - - -def some_function_to_convert_the_data(measurements: DataToExport): - """ Should be replaced here or in the model class to process the measurement """ - a = 0 - b = 1 - return [a, b] - - -class PIDModelTemplate(PIDModelGeneric): - limits = dict(max=dict(state=False, value=100), - min=dict(state=False, value=-100),) - konstants = dict(kp=0.1, ki=0.000, kd=0.0000) - - Nsetpoints = 2 # number of setpoints - setpoint_ini = [128, 128] # number and values of initial setpoints - setpoints_names = ['Xaxis', 'Yaxis'] # number and names of setpoints - - actuators_name = ["Xpiezo", "Ypiezo"] # names of actuator's control modules involved in the PID - detectors_name = ['Camera'] # names of detector's control modules involved in the PID - - params = [] # list of dict to initialize specific Parameters - - def __init__(self, pid_controller): - super().__init__(pid_controller) - - def update_settings(self, param): - """ - Get a parameter instance whose value has been modified by a user on the UI - Parameters - ---------- - param: (Parameter) instance of Parameter object - """ - if param.name() == '': - pass - - def ini_model(self): - super().ini_model() - - # add here other specifics initialization if needed - - def convert_input(self, measurements: DataToExport): - """ - Convert the measurements in the units to be fed to the PID (same dimensionality as the setpoint) - Parameters - ---------- - measurements: DataToExport - Data from the declared detectors from which the model extract a value of the same units as the setpoint - - Returns - ------- - InputFromDetector: the converted input in the setpoints units - - """ - - x, y = some_function_to_convert_the_data(measurements) - return DataToExport('pid inputs', - data=[DataCalculated('pid calculated', - data=[np.array([x]), - np.array([y])])]) - - def convert_output(self, outputs: List[float], dt: float, stab=True) -> DataToActuatorPID: - """ - Convert the output of the PID in units to be fed into the actuator - Parameters - ---------- - outputs: List of float - output value from the PID from which the model extract a value of the same units as the actuator - dt: float - Ellapsed time since the last call to this function - stab: bool - - Returns - ------- - OutputToActuator: the converted output - - """ - outputs = some_function_to_convert_the_pid_outputs(outputs, dt, stab) - return DataToActuatorPID('pid output', mode='rel', - data=[DataActuator(self.actuators_name[ind], data=outputs[ind]) - for ind in range(len(outputs))]) - - -if __name__ == '__main__': - main("BeamSteeringMockNoModel.xml") # some preset configured with the right actuators and detectors - - diff --git a/src/pymodaq_plugins_template/models/__init__.py b/src/pymodaq_plugins_template/models/__init__.py deleted file mode 100644 index 180d4dd..0000000 --- a/src/pymodaq_plugins_template/models/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created the 01/06/2023 - -@author: Sebastien Weber -""" From 45d1f0c0d06e73eaa0a36c36a98f50cef6b05b8e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 19:08:21 +0000 Subject: [PATCH 2/5] AGENTS.md: point to the existing sequencer choice models Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg --- AGENTS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 6a441f6..1e09b1a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -184,7 +184,8 @@ extensions already does the job and only the conversion of the measurements or o before the release that follows 5.3.3, so derive directly from it if you must support older releases). - The template ships no model on purpose. Start from the working examples of [`pymodaq_plugins_mockexamples`](https://github.com/PyMoDAQ/pymodaq_plugins_mockexamples) (`PIDModelBeamSteering`, - `PIDModelMockHeater`, `BayesianModelMock`, `DataMixerModelFit`) and from the page "Models of the extensions" of the + `PIDModelMockHeater`, `BayesianModelMock`, `DataMixerModelFit`; for the Sequencer, the choice models of + `pymodaq/extensions/sequencer/models`, which register with `@ChoiceModelFactory.register_choice()`) and from the page "Models of the extensions" of the PyMoDAQ documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and detectors of that package. - Do not use the old `pid_models` flag nor the word "preset" in new code: a model script that opens the Dashboard loads From 135facd484a803467573727d433f10eb10277ded Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 19:08:31 +0000 Subject: [PATCH 3/5] AGENTS.md: sequencer choice models register with a decorator Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg --- AGENTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 1e09b1a..4e003a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -179,14 +179,14 @@ extensions already does the job and only the conversion of the measurements or o - Set `models = true` in `[features]`; entry points are generated only then (`pymodaq.models`). - Create the `models/` folder at the root of the package, one model per module; the module name is the name shown in - the extension. The model is the class defined in the module that derives from the base class of the extension (it may + the extension. The model is the class defined in the module that derives from the base class of the extension (the + Sequencer instead registers its choice models with `@ChoiceModelFactory.register_choice()`; it may derive from your own intermediate class; PID and DataMixer only accepted a direct subclass of the generic base before the release that follows 5.3.3, so derive directly from it if you must support older releases). - The template ships no model on purpose. Start from the working examples of [`pymodaq_plugins_mockexamples`](https://github.com/PyMoDAQ/pymodaq_plugins_mockexamples) (`PIDModelBeamSteering`, `PIDModelMockHeater`, `BayesianModelMock`, `DataMixerModelFit`; for the Sequencer, the choice models of - `pymodaq/extensions/sequencer/models`, which register with `@ChoiceModelFactory.register_choice()`) and from the page "Models of the extensions" of the - PyMoDAQ documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and + `pymodaq/extensions/sequencer/models`) and from the page "Models of the extensions" of the PyMoDAQ documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and detectors of that package. - Do not use the old `pid_models` flag nor the word "preset" in new code: a model script that opens the Dashboard loads an experiment file. From bbdee30f5a199096a431d221f511dc510d910702 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 19:08:40 +0000 Subject: [PATCH 4/5] AGENTS.md: reword the models section Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg --- AGENTS.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4e003a9..e36f049 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -179,14 +179,16 @@ extensions already does the job and only the conversion of the measurements or o - Set `models = true` in `[features]`; entry points are generated only then (`pymodaq.models`). - Create the `models/` folder at the root of the package, one model per module; the module name is the name shown in - the extension. The model is the class defined in the module that derives from the base class of the extension (the - Sequencer instead registers its choice models with `@ChoiceModelFactory.register_choice()`; it may - derive from your own intermediate class; PID and DataMixer only accepted a direct subclass of the generic base - before the release that follows 5.3.3, so derive directly from it if you must support older releases). + the extension. The model is the class defined in the module that derives from the base class of the extension. It may + derive from your own intermediate class, but PID and DataMixer only accepted a direct subclass of the generic base + before the release that follows 5.3.3, so derive directly from it if you must support older releases. The Sequencer + is the exception: it does not look at base classes, you register each choice model with + `@ChoiceModelFactory.register_choice()`. - The template ships no model on purpose. Start from the working examples of [`pymodaq_plugins_mockexamples`](https://github.com/PyMoDAQ/pymodaq_plugins_mockexamples) (`PIDModelBeamSteering`, `PIDModelMockHeater`, `BayesianModelMock`, `DataMixerModelFit`; for the Sequencer, the choice models of - `pymodaq/extensions/sequencer/models`) and from the page "Models of the extensions" of the PyMoDAQ documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and + `pymodaq/extensions/sequencer/models`) and from the page "Models of the extensions" of the PyMoDAQ + documentation, which lists the methods to implement for each kind. Test a model with the mock actuators and detectors of that package. - Do not use the old `pid_models` flag nor the word "preset" in new code: a model script that opens the Dashboard loads an experiment file. From 971b71e8d4de066c6df91514d3403ec2e743b253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Sun, 11 Oct 2026 21:10:31 +0200 Subject: [PATCH 5/5] Update models feature description in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c5c381e..2db3617 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [features] # defines the plugin features contained into this plugin instruments = true # true if plugin contains instrument classes (else false, notice the lowercase for toml files) extensions = false # true if plugins contains dashboard extensions -models = false # true if plugins contains models of the extensions (PID, optimizers, data mixer, sequencer) +models = false # true if plugins contains models of the extensions (PID, optimizers, data mixer, sequencer, ...) h5exporters = false # true if plugin contains custom h5 file exporters scanners = false # true if plugin contains custom scan layout (daq_scan extensions)