SweepMeasurement: better design (employ the power of sweep objects)
- Dominant language
- Python
- Stars
- 459
- Forks
- 359
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 73
Description
## Scope
While implementing the "sweep module", a new `SweepMeasurement` class has been implemented ([see in PR 1107](https://github.com/QCoDeS/Qcodes/pull/1107/files#diff-4963cbfa7200ec4615523838cdbd1589R5) or in qcodes/sweep/measurement.py once #1107 is merged).
The class is implemented by simply subclassing from `Measurement` class, and adding a `register_sweep` method.
## Problem
The implementation is lacking design for the following reasons.
### 1
Thanks to the direct inheritance, `register_parameter` methods can be called on `SweepMeasurement` objects. But this is NOT desirable. The whole point of the `SweepMeasurement` is to get away from `register_parameter`, and use a sweep object for both "measurement definition" and "measurement execution". So, `SweepMeasurement` objects should not have `register_parameter`-like methods. If there is a need to add or remove parameters, that should be done through the sweep object.
### 2
Since `SweepMeasurement` make sense only for once sweep, what is the need for an explicit `register_sweep` method? Why not pass the sweep object directly to the constructor of the `SweepMeasurement`?
Compare two lines
```
sweep_measurement = SweepMeasurement()
sweep_measurement.register_sweep(total_sweep_object)
```
with one line
```
sweep_measurement = SweepMeasurement(total_sweep_object)
```
### 3
Thanks to the sweep object infrastructure, the measurement execution code itself becomes very concise, and more importantly generic. For example:
```
with sweep_measurement.run() as data_saver:
for data_point in total_sweep_object:
data_saver.add_results(*data_point.items())
```
Why not implement a method on `SweepMeasurement` class that does that since `SweepMeasurement` objects are created based on a sweep object and they can contain it inside?
Since the `run` method is considered, it is also worth noting that the `run` method of a `Measurement` object does not actually "run" anything - it just initiates a data set and returns a context manager from within which measurement results can be saved (e.g. added to the data set). On the other hand, a `run` method of the `SweepMeasurement` class can indeed "run" the experiment, because the experiment definition is already known from the sweep object.
## Proposed solution
- Make a private base class `_MeasurementBase` (or `_MeasurementWithDataSetBase`).
- Make `Measurement` class inherit from '_MeasurementBase`, and implement only the register parameter methods in it (like `register_parameter`).
- Make `SweepMeasurement` class inherit from `_MeasurementBase`. Instead of implementing a `register_sweep` method, make the sweep object be an argument for its constructor.
- Implement a `run` method of the `SweepMeasurement` such that it actually "run" the measurement. This might also require renaming of the `run` method of the `Measurement` class.
@sohailc @WilliamHPNielsen @jenshnielsen @Dominik-Vogel
Contributor guide
Assessment
This issue has not been assessed yet.