iqm-pulse 10.3.0__tar.gz → 10.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/CHANGELOG.rst +17 -0
  2. {iqm_pulse-10.3.0/src/iqm_pulse.egg-info → iqm_pulse-10.5.0}/PKG-INFO +1 -1
  3. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/pyproject.toml +3 -3
  4. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/base_utils.py +1 -1
  5. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/builder.py +33 -11
  6. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/circuit_operations.py +7 -7
  7. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/__init__.py +2 -2
  8. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/default_gates.py +37 -23
  9. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/rz.py +1 -1
  10. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/channel.py +1 -1
  11. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/instructions.py +3 -3
  12. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/schedule.py +3 -3
  13. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/base.py +2 -2
  14. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/waveforms.py +1 -1
  15. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/validation.py +3 -3
  16. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0/src/iqm_pulse.egg-info}/PKG-INFO +1 -1
  17. iqm_pulse-10.5.0/version.txt +1 -0
  18. iqm_pulse-10.3.0/version.txt +0 -1
  19. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/LICENSE.txt +0 -0
  20. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/MANIFEST.in +0 -0
  21. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/README.rst +0 -0
  22. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/API.rst +0 -0
  23. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/Makefile +0 -0
  24. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/.gitignore +0 -0
  25. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/css/custom.css +0 -0
  26. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/favicon.ico +0 -0
  27. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/feedback_timing.svg +0 -0
  28. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/logo.png +0 -0
  29. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/playlist_breakdown.svg +0 -0
  30. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/pulse_timing.svg +0 -0
  31. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_static/images/readout_timing.svg +0 -0
  32. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_templates/autosummary-class-template.rst +0 -0
  33. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/_templates/autosummary-module-template.rst +0 -0
  34. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/changelog.rst +0 -0
  35. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/concepts.rst +0 -0
  36. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/conf.py +0 -0
  37. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/custom_gates.rst +0 -0
  38. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/index.rst +0 -0
  39. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/license.rst +0 -0
  40. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/pulse_timing.rst +0 -0
  41. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/references.bib +0 -0
  42. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/references.rst +0 -0
  43. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/docs/using_builder.rst +0 -0
  44. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/requirements/base.in +0 -0
  45. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/requirements/base.txt +0 -0
  46. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/setup.cfg +0 -0
  47. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/setup.py +0 -0
  48. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/__init__.py +0 -0
  49. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gate_implementation.py +0 -0
  50. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/barrier.py +0 -0
  51. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/conditional.py +0 -0
  52. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/cz.py +0 -0
  53. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/delay.py +0 -0
  54. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/enums.py +0 -0
  55. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/flux_multiplexer.py +0 -0
  56. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/measure.py +0 -0
  57. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/move.py +0 -0
  58. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/prx.py +0 -0
  59. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/reset.py +0 -0
  60. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/sx.py +0 -0
  61. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/gates/u.py +0 -0
  62. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/__init__.py +0 -0
  63. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/fast_drag.py +0 -0
  64. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/hd_drag.py +0 -0
  65. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/playlist.py +0 -0
  66. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/__init__.py +0 -0
  67. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/templates/playlist_inspection.jinja2 +0 -0
  68. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/templates/static/logo.png +0 -0
  69. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/templates/static/moment.min.js +0 -0
  70. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.css +0 -0
  71. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.js +0 -0
  72. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/py.typed +0 -0
  73. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/quantum_ops.py +0 -0
  74. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/scheduler.py +0 -0
  75. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/timebox.py +0 -0
  76. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm/pulse/utils.py +0 -0
  77. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm_pulse.egg-info/SOURCES.txt +0 -0
  78. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm_pulse.egg-info/dependency_links.txt +0 -0
  79. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm_pulse.egg-info/requires.txt +0 -0
  80. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/src/iqm_pulse.egg-info/top_level.txt +0 -0
  81. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/tests/.pylintrc +0 -0
  82. {iqm_pulse-10.3.0 → iqm_pulse-10.5.0}/tests/__init__.py +0 -0
@@ -2,6 +2,23 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Version 10.5.0 (2025-09-03)
6
+ ===========================
7
+
8
+ Features
9
+ --------
10
+
11
+ - Enable ruff rule for missing annotations and mark exemptions.
12
+
13
+ Version 10.4.0 (2025-08-12)
14
+ ===========================
15
+
16
+ Features
17
+ --------
18
+
19
+ - Allow deprecating quantum operations and/or their implementations while still preserving them in the quantum operation
20
+ library (the names of deprecated canonical operations are still reserved).
21
+
5
22
  Version 10.3.0 (2025-08-11)
6
23
  ===========================
7
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-pulse
3
- Version: 10.3.0
3
+ Version: 10.5.0
4
4
  Summary: A Python-based project for providing interface and implementations for control pulses.
5
5
  Author-email: IQM Finland Oy <info@meetiqm.com>
6
6
  License: Apache License
@@ -52,7 +52,7 @@ nb_diff_ignore = [ "/metadata/language_info", "/metadata/widgets", "/cells/*/exe
52
52
 
53
53
  [tool.ruff.lint]
54
54
  ignore = [ "D203", "D213",]
55
- select = [ "E4", "E7", "E9", "E5", "F", "Q", "PL", "I", "D", "UP007", "UP006", "UP035",]
55
+ select = [ "E4", "E7", "E9", "E5", "F", "Q", "PL", "I", "D", "UP007", "UP006", "UP035", "ANN001", "ANN201", "ANN202",]
56
56
  unfixable = [ "F401",]
57
57
 
58
58
  [tool.ruff.lint.isort]
@@ -65,9 +65,9 @@ relative-imports-order = "closest-to-furthest"
65
65
  [tool.ruff.lint.per-file-ignores]
66
66
  "**/__init__.py" = [ "F401", "PLR0402",]
67
67
  "**/docs/*" = [ "E402", "D100",]
68
- "**/setup.py" = [ "D100", "D103", "I001",]
68
+ "**/setup.py" = [ "D100", "D103", "I001", "ANN201",]
69
69
  "**/src/*" = [ "PLR2004", "D400", "D415", "D205", "D401", "D417", "D100", "D101", "D107", "D102", "D105", "D103", "D404", "D104",]
70
- "**/tests/*" = [ "F632", "PLR2004", "PLR0402", "PLC0414", "D",]
70
+ "**/tests/*" = [ "F632", "PLR2004", "PLR0402", "PLC0414", "D", "ANN001", "ANN201", "ANN202",]
71
71
 
72
72
  [tool.ruff.lint.pylint]
73
73
  max-args = 8
@@ -24,7 +24,7 @@ from typing import Any
24
24
  import numpy as np
25
25
 
26
26
 
27
- def merge_dicts(A: dict, B: dict, path=(), merge_nones: bool = True) -> dict:
27
+ def merge_dicts(A: dict, B: dict, path=(), merge_nones: bool = True) -> dict: # noqa: ANN001
28
28
  """Merge two dictionaries recursively, leaving the originals unchanged.
29
29
 
30
30
  Args:
@@ -45,7 +45,7 @@ from iqm.pulse.gate_implementation import (
45
45
  OpCalibrationDataTree,
46
46
  )
47
47
  from iqm.pulse.gates import _validate_implementation, get_implementation_class
48
- from iqm.pulse.gates.default_gates import _quantum_ops_library
48
+ from iqm.pulse.gates.default_gates import _deprecated_implementations, _deprecated_ops, _quantum_ops_library
49
49
  from iqm.pulse.playlist.channel import ChannelProperties, ProbeChannelProperties
50
50
  from iqm.pulse.playlist.instructions import (
51
51
  AcquisitionMethod,
@@ -184,8 +184,12 @@ def validate_quantum_circuit(
184
184
  def build_quantum_ops(ops: dict[str, dict[str, Any]]) -> QuantumOpTable:
185
185
  """Builds the table of known quantum operations.
186
186
 
187
- Hardcoded default native ops table is extended by the ones in ``ops``.
188
- In case of name collisions, the content of ``ops`` takes priority over the defaults.
187
+ Hardcoded canonical ops table is extended by the ones in ``ops``.
188
+ In case of name collisions, the content of ``ops`` takes priority over the defaults,
189
+ with the following caveats:
190
+
191
+ * canonical implementation names cannot be redefined, and
192
+ * for canonical operations you can only change :attr:`implementations` and :attr:`defaults_for_locus`.
189
193
 
190
194
  Args:
191
195
  ops: Contents of the ``gate_definitions`` section defining
@@ -204,7 +208,23 @@ def build_quantum_ops(ops: dict[str, dict[str, Any]]) -> QuantumOpTable:
204
208
  ValueError: Operation attributes don't match defaults or are invalid.
205
209
 
206
210
  """
207
- op_table = copy.deepcopy(_quantum_ops_library)
211
+ # build the table of native ops
212
+ op_table = {}
213
+ for op_name, op in _quantum_ops_library.items():
214
+ # filter out deprecated ops, unless requested by the user in ``ops``
215
+ if op_name in _deprecated_ops and op_name not in ops:
216
+ continue
217
+
218
+ new_op = copy.deepcopy(op) # to prevent modifications to the hardcoded table
219
+ if (deprecated_impls := _deprecated_implementations.get(op_name)) is not None:
220
+ # filter out deprecated implementations
221
+ non_deprecated = {
222
+ impl_name: impl for impl_name, impl in op.implementations.items() if impl_name not in deprecated_impls
223
+ }
224
+ new_op = replace(op, implementations=non_deprecated)
225
+ op_table[op_name] = new_op
226
+
227
+ # add ops defined by the user
208
228
  for op_name, op_definition in ops.items():
209
229
  # prepare the implementations
210
230
  implementations: dict[str, type[GateImplementation]] = {}
@@ -236,9 +256,9 @@ def build_quantum_ops(ops: dict[str, dict[str, Any]]) -> QuantumOpTable:
236
256
  f"appear in the implementations dict."
237
257
  )
238
258
 
239
- # prepare a new op, or modify the existing one
240
- if (old_op := op_table.get(op_name)) is not None:
241
- # known op: only some fields can be redefined, and they have been popped out already
259
+ if (old_op := _quantum_ops_library.get(op_name)) is not None:
260
+ # modify a canonical operation
261
+ # only some fields can be modified, and they have been popped out already from op_definition
242
262
  if op_definition:
243
263
  # TODO this should be an error, but there are so many old experiment.yml files in use
244
264
  # that still have the old syntax that being strict about this would be disruptive.
@@ -247,15 +267,17 @@ def build_quantum_ops(ops: dict[str, dict[str, Any]]) -> QuantumOpTable:
247
267
  f"'{op_name}' is a canonical operation, which means the fields {set(op_definition)} "
248
268
  "provided by the user may not be changed."
249
269
  )
250
- op_table[op_name] = replace(old_op, implementations=implementations, defaults_for_locus=defaults_for_locus)
270
+
271
+ op = replace(old_op, implementations=implementations, defaults_for_locus=defaults_for_locus)
251
272
  else:
252
- # new op
253
- op_table[op_name] = QuantumOp(
273
+ # entirely new quantum operation defined by the user
274
+ op = QuantumOp(
254
275
  name=op_name,
255
276
  implementations=implementations,
256
277
  defaults_for_locus=defaults_for_locus,
257
278
  **op_definition,
258
279
  )
280
+ op_table[op_name] = op
259
281
 
260
282
  return op_table
261
283
 
@@ -1474,7 +1496,7 @@ class ScheduleBuilder:
1474
1496
  """
1475
1497
 
1476
1498
  def _shortcut_mthd(
1477
- self,
1499
+ self, # noqa: ANN001
1478
1500
  locus: Iterable[str],
1479
1501
  impl_name: str | None = None,
1480
1502
  *,
@@ -145,7 +145,7 @@ def get_unitary_from_circuit(
145
145
  return unitary
146
146
 
147
147
 
148
- def _get_qubit_order_from_circuit(circuit: list[CircuitOperation]):
148
+ def _get_qubit_order_from_circuit(circuit: list[CircuitOperation]): # noqa: ANN202
149
149
  """Get all qubits which are in the circuit in order."""
150
150
  # unique items, in the same order
151
151
  return list(dict.fromkeys(qb for op in circuit for qb in op.locus))
@@ -278,7 +278,7 @@ class CircuitOperationList(list):
278
278
  if self.table[op_name].arity:
279
279
  self._set_specific_operation_shortcut(op_name)
280
280
 
281
- def __getitem__(self, item) -> CircuitOperationList | CircuitOperation: # type: ignore[override] # type: ignore[override] # type: ignore[override]
281
+ def __getitem__(self, item) -> CircuitOperationList | CircuitOperation: # type: ignore[override] # type: ignore[override] # type: ignore[override] # noqa: ANN001
282
282
  """For the builtin list, this method is used both for accessing a single element: ``mylist[0]`` and accessing
283
283
  a slice: ``mylist[1:3]``. The latter should generate a new CircuitOperationList, so we override the method to
284
284
  ensure that it does.
@@ -290,12 +290,12 @@ class CircuitOperationList(list):
290
290
 
291
291
  return result
292
292
 
293
- def __add__(self, other) -> CircuitOperationList:
293
+ def __add__(self, other) -> CircuitOperationList: # noqa: ANN001
294
294
  new = CircuitOperationList(list.__add__(self, other), qubits=self.qubits, table=self.table)
295
295
 
296
296
  return new
297
297
 
298
- def __mul__(self, other) -> CircuitOperationList:
298
+ def __mul__(self, other) -> CircuitOperationList: # noqa: ANN001
299
299
  new = CircuitOperationList(list.__mul__(self, other), qubits=self.qubits, table=self.table)
300
300
  return new
301
301
 
@@ -377,7 +377,7 @@ class CircuitOperationList(list):
377
377
 
378
378
  def compose(
379
379
  self,
380
- other,
380
+ other, # noqa: ANN001
381
381
  locus_indices: list[int] | None = None,
382
382
  ) -> Self:
383
383
  """A safer way to add circuits together, but will probably take time.
@@ -482,8 +482,8 @@ class CircuitOperationList(list):
482
482
  num_params = len(op.params)
483
483
  arity = op.arity
484
484
 
485
- def _add_specific_op(
486
- self,
485
+ def _add_specific_op( # noqa: ANN202
486
+ self, # noqa: ANN001
487
487
  *args_and_locus,
488
488
  impl_name: str | None = None,
489
489
  ):
@@ -46,7 +46,7 @@ from iqm.pulse.gates.cz import (
46
46
  FluxPulseGate_CRF_CRF,
47
47
  FluxPulseGate_TGSS_CRF,
48
48
  )
49
- from iqm.pulse.gates.default_gates import _default_implementations, _quantum_ops_library
49
+ from iqm.pulse.gates.default_gates import _implementation_library, _quantum_ops_library
50
50
  from iqm.pulse.gates.delay import Delay
51
51
  from iqm.pulse.gates.flux_multiplexer import FluxMultiplexer_SampleLinear
52
52
  from iqm.pulse.gates.measure import Measure_Constant, Measure_Constant_Qnd, Shelved_Measure_Constant
@@ -157,7 +157,7 @@ def _validate_implementation(
157
157
  ValueError: A canonical implementation name is being redefined.
158
158
 
159
159
  """
160
- default_implementations = _default_implementations.get(op_name, {})
160
+ default_implementations = _implementation_library.get(op_name, {})
161
161
 
162
162
  # check if the implementation name is canonical for this op
163
163
  if (impl_class := default_implementations.get(impl_name)) is not None:
@@ -15,7 +15,7 @@
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- from typing import TYPE_CHECKING
18
+ from typing import TYPE_CHECKING, Final
19
19
 
20
20
  import numpy as np
21
21
 
@@ -63,7 +63,7 @@ if TYPE_CHECKING:
63
63
  from iqm.pulse.gate_implementation import GateImplementation
64
64
 
65
65
 
66
- _default_implementations: dict[str, dict[str, type[GateImplementation]]] = {
66
+ _implementation_library: dict[str, dict[str, type[GateImplementation]]] = {
67
67
  "barrier": {"": Barrier},
68
68
  "delay": {"wait": Delay},
69
69
  "measure": {
@@ -105,9 +105,11 @@ _default_implementations: dict[str, dict[str, type[GateImplementation]]] = {
105
105
  "reset_wait": {"reset_wait": Reset_Wait},
106
106
  "flux_multiplexer": {"sample_linear": FluxMultiplexer_SampleLinear},
107
107
  }
108
- """Canonical implementation names for the canonical quantum operations.
109
- A collection of mappings between default implementation names and their GateImplementation classes,
110
- for different gates."""
108
+ """For each canonical quantum operation name, maps its canonical implementation implementation names
109
+ to their GateImplementation classes.
110
+
111
+ Canonical names are reserved, and the users cannot redefine them.
112
+ """
111
113
 
112
114
  _quantum_ops_library = {
113
115
  op.name: op
@@ -115,101 +117,113 @@ _quantum_ops_library = {
115
117
  QuantumOp(
116
118
  "barrier",
117
119
  0,
118
- implementations=_default_implementations["barrier"], # type: ignore[arg-type]
120
+ implementations=_implementation_library["barrier"],
119
121
  symmetric=True,
120
122
  ),
121
123
  QuantumOp(
122
124
  "delay",
123
125
  0,
124
126
  ("duration",),
125
- implementations=_default_implementations["delay"], # type: ignore[arg-type]
127
+ implementations=_implementation_library["delay"],
126
128
  symmetric=True,
127
129
  ),
128
130
  QuantumOp(
129
131
  "measure",
130
132
  0,
131
133
  ("key",),
132
- implementations=_default_implementations["measure"], # type: ignore[arg-type]
134
+ implementations=_implementation_library["measure"],
133
135
  factorizable=True,
134
136
  ),
135
137
  QuantumOp(
136
138
  "prx",
137
139
  1,
138
140
  ("angle", "phase"),
139
- implementations=_default_implementations["prx"], # type: ignore[arg-type]
141
+ implementations=_implementation_library["prx"],
140
142
  unitary=get_unitary_prx,
141
143
  ),
142
144
  QuantumOp(
143
145
  "prx_12",
144
146
  1,
145
147
  ("angle", "phase"),
146
- implementations=_default_implementations["prx_12"], # type: ignore[arg-type]
148
+ implementations=_implementation_library["prx_12"],
147
149
  ),
148
150
  QuantumOp(
149
151
  "u",
150
152
  1,
151
153
  ("theta", "phi", "lam"),
152
- implementations=_default_implementations["u"], # type: ignore[arg-type]
154
+ implementations=_implementation_library["u"],
153
155
  unitary=get_unitary_u,
154
156
  ),
155
157
  QuantumOp(
156
158
  "sx",
157
159
  1,
158
- implementations=_default_implementations["sx"], # type: ignore[arg-type]
160
+ implementations=_implementation_library["sx"],
159
161
  unitary=lambda: get_unitary_prx(np.pi / 2, 0),
160
162
  ),
161
163
  QuantumOp(
162
164
  "rz",
163
165
  1,
164
166
  ("angle",),
165
- implementations=_default_implementations["rz"], # type: ignore[arg-type]
167
+ implementations=_implementation_library["rz"],
166
168
  unitary=get_unitary_rz,
167
169
  ),
168
170
  QuantumOp(
169
171
  "rz_physical",
170
172
  1,
171
- implementations=_default_implementations["rz_physical"], # type: ignore[arg-type]
173
+ implementations=_implementation_library["rz_physical"],
172
174
  ),
173
175
  QuantumOp(
174
176
  "cz",
175
177
  2,
176
178
  (),
177
- implementations=_default_implementations["cz"], # type: ignore[arg-type]
179
+ implementations=_implementation_library["cz"],
178
180
  symmetric=True,
179
181
  unitary=lambda: np.diag([1.0, 1.0, 1.0, -1.0]),
180
182
  ),
181
183
  QuantumOp(
182
184
  "move",
183
185
  2,
184
- implementations=_default_implementations["move"], # type: ignore[arg-type]
186
+ implementations=_implementation_library["move"],
185
187
  ),
186
188
  QuantumOp(
187
189
  "cc_prx",
188
190
  1,
189
191
  ("angle", "phase", "feedback_qubit", "feedback_key"),
190
- implementations=_default_implementations["cc_prx"], # type: ignore[arg-type]
192
+ implementations=_implementation_library["cc_prx"],
191
193
  ),
192
194
  QuantumOp(
193
195
  "reset",
194
196
  0,
195
- implementations=_default_implementations["reset"], # type: ignore[arg-type]
197
+ implementations=_implementation_library["reset"],
196
198
  symmetric=True,
197
199
  factorizable=True,
198
200
  ),
199
201
  QuantumOp(
200
202
  "reset_wait",
201
203
  0,
202
- implementations=_default_implementations["reset_wait"], # type: ignore[arg-type]
204
+ implementations=_implementation_library["reset_wait"],
203
205
  symmetric=True,
204
206
  factorizable=True,
205
207
  ),
206
208
  QuantumOp(
207
209
  "flux_multiplexer",
208
210
  0,
209
- implementations=_default_implementations["flux_multiplexer"], # type: ignore[arg-type]
211
+ implementations=_implementation_library["flux_multiplexer"],
210
212
  ),
211
213
  ]
212
214
  }
213
- """Library of the current canonical quantum operations provided by iqm-pulse."""
214
- # NOTE If a canonical operation is removed in the future, consider adding a second dict for former
215
- # canonical operations so that we retain information about them.
215
+ """Canonical quantum operations provided by iqm-pulse.
216
+
217
+ Their names are reserved, and the users cannot redefine them.
218
+ """
219
+
220
+ _deprecated_ops: Final[set[str]] = set()
221
+ """Names of canonical quantum operations that are deprecated.
222
+
223
+ They are not included by default in ScheduleBuilder unless the user specifically requests them."""
224
+ _deprecated_implementations: Final[dict[str, set[str]]] = {}
225
+ """For each canonical quantum operation name, canonical implementation names that are deprecated.
226
+
227
+ They are not included by default in ScheduleBuilder unless the user specifically requests them."""
228
+ # TODO: deprecate gaussian_smoothed_square and everything with the tgss waveform as that is considered inferior to crf.
229
+ # TODO: deprecate PRX_drag_gaussian
@@ -253,7 +253,7 @@ class RZ_PRX_Composite(CompositeGate):
253
253
 
254
254
  registered_gates = ("prx",)
255
255
 
256
- def __init__(self, parent, name, locus, calibration_data, builder):
256
+ def __init__(self, parent, name, locus, calibration_data, builder): # noqa: ANN001
257
257
  super().__init__(parent, name, locus, calibration_data, builder)
258
258
 
259
259
  def __call__(self, angle: float) -> TimeBox:
@@ -272,7 +272,7 @@ class ChannelDescription:
272
272
  self.waveform_table.append(wave)
273
273
  return idx
274
274
 
275
- def _lookup_or_insert_instruction(self, instruction) -> int:
275
+ def _lookup_or_insert_instruction(self, instruction) -> int: # noqa: ANN001
276
276
  new_idx = len(self.instruction_table)
277
277
  idx = self._reverse_instruction_index.setdefault(instruction, new_idx)
278
278
  if idx == new_idx:
@@ -103,7 +103,7 @@ class RealPulse(Instruction):
103
103
  scale: float
104
104
  """Scaling factor for the waveform."""
105
105
 
106
- def validate(self):
106
+ def validate(self): # noqa: ANN201
107
107
  super().validate()
108
108
  if abs(self.scale) > 1.0:
109
109
  raise ValueError(f"RealPulse.scale {self.scale} not in [-1, 1].")
@@ -149,7 +149,7 @@ class IQPulse(Instruction):
149
149
  all pulses that are played after it on the channel, in radians.
150
150
  """
151
151
 
152
- def validate(self):
152
+ def validate(self): # noqa: ANN201
153
153
  super().validate()
154
154
  if abs(self.scale_i) > 1.0:
155
155
  raise ValueError(f"IQPulse.scale_i {self.scale_i} not in [-1, 1].")
@@ -169,7 +169,7 @@ class ConditionalInstruction(Instruction):
169
169
  outcomes: tuple[Instruction, ...]
170
170
  """Maps possible outcomes of the condition to the corresponding instructions."""
171
171
 
172
- def validate(self):
172
+ def validate(self): # noqa: ANN201
173
173
  super().validate()
174
174
  if not self.outcomes:
175
175
  raise ValueError("There must be at least one outcome.")
@@ -78,7 +78,7 @@ class Segment:
78
78
  def __len__(self) -> int:
79
79
  return len(self._instructions)
80
80
 
81
- def __getitem__(self, key):
81
+ def __getitem__(self, key): # noqa: ANN001
82
82
  return self._instructions[key]
83
83
 
84
84
  def __reversed__(self):
@@ -229,7 +229,7 @@ class Schedule:
229
229
  s += "|\n"
230
230
  return s
231
231
 
232
- def items(self):
232
+ def items(self): # noqa: ANN201
233
233
  """Iterator over the schedule channel names and segments."""
234
234
  return self._contents.items()
235
235
 
@@ -313,7 +313,7 @@ class Schedule:
313
313
  }
314
314
  return self
315
315
 
316
- def front_pad_in_seconds(self, to_duration: float, channel_properties: dict[str, ChannelProperties]):
316
+ def front_pad_in_seconds(self, to_duration: float, channel_properties: dict[str, ChannelProperties]): # noqa: ANN201
317
317
  """Modifies the schedule in place by front-padding it with :class:`.Wait` instructions.
318
318
 
319
319
  The new duration is given in seconds, and this method works also with variable sample rates.
@@ -31,7 +31,7 @@ import numpy as np
31
31
  from iqm.pulse.playlist.playlist import Playlist
32
32
 
33
33
 
34
- def _numpy_to_builtin_types(data: list[tuple[str, Any]]):
34
+ def _numpy_to_builtin_types(data: list[tuple[str, Any]]): # noqa: ANN202
35
35
  """Convert selected ``numpy`` types to Python's built-in types.
36
36
 
37
37
  This helper function is to be used for converting dataclasses into
@@ -57,7 +57,7 @@ def _numpy_to_builtin_types(data: list[tuple[str, Any]]):
57
57
  def _get_waveform(wave: Waveform, scale: float, wave_q: Waveform | None = None, scale_q: float | None = None) -> str:
58
58
  import matplotlib.pyplot as plt
59
59
 
60
- def fig_to_base64(fig):
60
+ def fig_to_base64(fig): # noqa: ANN001, ANN202
61
61
  img = io.BytesIO()
62
62
  fig.savefig(img, format="png", bbox_inches="tight")
63
63
  img.seek(0)
@@ -364,7 +364,7 @@ class Chirp(Waveform):
364
364
  alpha: float = 0.05
365
365
  phase: float = 0
366
366
 
367
- def _sample(self, sample_coords):
367
+ def _sample(self, sample_coords): # noqa: ANN001, ANN202
368
368
  chirpfreq = np.linspace(self.freq_start, self.freq_stop, len(sample_coords))
369
369
  chirpphase = 2 * np.pi * np.cumsum(chirpfreq) + self.phase
370
370
  wave = np.exp(1j * chirpphase) * ss.windows.tukey(len(sample_coords), self.alpha)
@@ -126,7 +126,7 @@ class AWGScheduleValidationError(Exception):
126
126
  class InvalidInstructionError(Exception):
127
127
  """Error raised when encountering an invalid instruction."""
128
128
 
129
- def __init__(self, instruction, issue_string="unknown reason"):
129
+ def __init__(self, instruction, issue_string="unknown reason"): # noqa: ANN001
130
130
  self.issue_string = issue_string
131
131
  self.instruction = instruction
132
132
  super().__init__(issue_string)
@@ -135,7 +135,7 @@ class InvalidInstructionError(Exception):
135
135
  return f"{self.issue_string} (in {self.instruction})"
136
136
 
137
137
 
138
- def validate_instruction_and_wf_length(instruction: Instruction):
138
+ def validate_instruction_and_wf_length(instruction: Instruction): # noqa: ANN201
139
139
  """Validate that instruction and waveform lengths match
140
140
 
141
141
  Args:
@@ -156,7 +156,7 @@ def validate_instruction_and_wf_length(instruction: Instruction):
156
156
  raise InvalidInstructionError(instruction, "scale not in -1..1")
157
157
 
158
158
 
159
- def validate_awg_and_schedule_compatibility(
159
+ def validate_awg_and_schedule_compatibility( # noqa: ANN201
160
160
  channel_description: ChannelDescription, device_constraints: AWGScheduleValidationData
161
161
  ):
162
162
  """Validates that the given playlist is compatible with the provided AWG data.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-pulse
3
- Version: 10.3.0
3
+ Version: 10.5.0
4
4
  Summary: A Python-based project for providing interface and implementations for control pulses.
5
5
  Author-email: IQM Finland Oy <info@meetiqm.com>
6
6
  License: Apache License
@@ -0,0 +1 @@
1
+ 10.5.0
@@ -1 +0,0 @@
1
- 10.3.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes