Skip to content

Commit

Permalink
Make qualang-tools compatible with python 3.12 (#249)
Browse files Browse the repository at this point in the history
* update pyproject.toml to allow python 3.12

* support 3.12

* add tests for python 3.8, 3.12

* add per-python artifact

* fix test command

* update package name

* update flake8

* update lock file

* ignore E231

* Fix flake8 E226 errors

* Remove E231 error

* flake8 remaining fixes

* Change flake8 to 5.0.4 to satisfy python 3.8

* Remove whitespace, ignore errors in flake8

* fix failing test due to differing numpy behaviour

---------

Co-authored-by: Yoav Romach <[email protected]>
Co-authored-by: Serwan Asaad <[email protected]>
Co-authored-by: Serwan Asaad <[email protected]>
  • Loading branch information
4 people authored Dec 10, 2024
1 parent 54b2b16 commit be92404
Show file tree
Hide file tree
Showing 17 changed files with 682 additions and 527 deletions.
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[flake8]
max-line-length = 88
select = C,E,F,W,B,B950
ignore = E203, E501, W503, E741, B950, F405, F403
ignore = E203, E501, W503, E741, B950, F405, F403, E231, E713, W604, E241, E221, E222, E225
exclude = **/tests/**
per-file-ignores =
qualang_tools/config/components.py:E743
21 changes: 16 additions & 5 deletions .github/workflows/on-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ jobs:
env:
JUNIT_REPORT_PATH: pytest-junit-report
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8, 3.10.13, 3.12]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: 3.10.13
python-version: ${{ matrix.python-version }}

- name: Setup pip Cache
id: cache-pip
Expand Down Expand Up @@ -43,8 +47,8 @@ jobs:
- name: Check linting
run: poetry run poe lint

- name: Test
run: poetry run poe test --junitxml=${JUNIT_REPORT_PATH}/report.xml
- name: Run tests
run: poetry run poe test --junitxml=test-results-${{ matrix.python-version }}.xml

- name: Build
run: poetry build
Expand All @@ -66,10 +70,17 @@ jobs:
with:
files: ${{env.JUNIT_REPORT_PATH}}/*.xml

- name: Upload test results
if: always()
uses: actions/upload-artifact@v3
with:
name: test-results-python-${{ matrix.python-version }}
path: test-results-${{ matrix.python-version }}.xml

- name: Upload dist
uses: actions/upload-artifact@v4
with:
name: python_pkg
name: python_pkg_py${{ matrix.python-version }}
path: |
dist/*.tar.gz
dist/*.whl
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## [Unreleased]
### Added
- Support for Python 3.12

### Fixed
- external_frameworks/qcodes - Fixed the driver to be compatible with qm-qua==1.2.1.

Expand Down
2 changes: 1 addition & 1 deletion examples/callable_from_qua/qua_print.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
def qua_print(*args):
text = ""
for i in range(0, len(args) - 1, 2):
text += f"{args[i]} = {args[i+1]} | "
text += f"{args[i]} = {args[i + 1]} | "
print(text)


Expand Down
1,068 changes: 598 additions & 470 deletions poetry.lock

Large diffs are not rendered by default.

46 changes: 29 additions & 17 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,33 @@ version = "v0.18.1"
description = "The qualang_tools package includes various tools related to QUA programs in Python"
authors = ["Quantum Machines <[email protected]>"]
license = "BSD-3-Clause"
packages = [
{ include = "qualang_tools" }
]
include = [
]
exclude = [
"**/tests/**",
]
packages = [{ include = "qualang_tools" }]
include = []
exclude = ["**/tests/**"]
readme = "README.md"
homepage = "https://github.com/qua-platform/py-qua-tools"

[tool.poetry.dependencies]
python = ">=3.8,<3.12"
python = ">=3.8, <3.13"
matplotlib = "^3.4.2"
numpy = "^1.17.0"
qm-qua = "^1.1.7"
scipy = "^1.7.1"
numpy = [
{ version = ">=1.17.0, <2", python = ">=3.8,<3.12" },
{ version = ">=1.26.0, <2", python = ">=3.12" },
]
qm-qua = { version = ">=1.1.7", python = ">=3.8,<3.13" }
scipy = [
{ version = ">=1.7.1, <1.10.0", python = ">=3.8,<3.12" },
{ version = ">=1.11.0", python = ">=3.12" },
]
pandas = { version = ">=1.2.4", optional = true }
dash = { version = "^2.0.0", optional = true }
dash-html-components = { version = "^2.0.0", optional = true }
dash-core-components = { version = "^2.0.0", optional = true }
dash-bootstrap-components = { version = "^1.0.0", optional = true }
dash-bootstrap-components = { version = "^1.6.0", optional = true, python = ">=3.8,<4" }
dash-cytoscape = { version = "^0.3.0", optional = true }
dash-table = { version = "^5.0.0", optional = true }
dash-dangerously-set-inner-html = { version = "^0.0.2", optional = true }
docutils = { version = ">=0.14.0", optional = true }
docutils = { version = ">=0.14.0 <= 0.21", optional = true }
waitress = { version = "^2.0.0", optional = true }
dill = { version = "^0.3.4", optional = true }
pypiwin32 = { version = "^223", optional = true }
Expand All @@ -41,13 +42,24 @@ grpclib = "0.4.5"
[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
black = "^24.3"
poethepoet = "^0.11.0"
flake8 = "^4.0.1"
poethepoet = "^0.18.0"
flake8 = "^5.0.4"
setuptools = "^69.0.2"

[tool.poetry.extras]
interplot = ["dill", "pypiwin32", "ipython"]
configbuilder = ["pandas", "dash", "dash-html-components", "dash-core-components", "dash-bootstrap-components", "dash-cytoscape", "dash-table", "dash-dangerously-set-inner-html", "docutils", "waitress"]
configbuilder = [
"pandas",
"dash",
"dash-html-components",
"dash-core-components",
"dash-bootstrap-components",
"dash-cytoscape",
"dash-table",
"dash-dangerously-set-inner-html",
"docutils",
"waitress",
]
datahandler = ["xarray", "netcdf4"]

[tool.black]
Expand Down
10 changes: 5 additions & 5 deletions qualang_tools/addons/InteractivePlotLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ def predefined_fit(self, req="g"):
"initial_guess": [omega, 1, 1, 0],
"func": "sin*exp",
"y_scale": y_extra_scale,
"text": lambda a: f"f = {a[0]/(2*np.pi)} [Hz]\n tau = {1/a[1]} [s]\n amp = {a[2]*y_extra_scale}\n y_offset={a[3]*y_extra_scale}",
"text": lambda a: f"f = {a[0] / (2 * np.pi)} [Hz]\n tau = {1 / a[1]} [s]\n amp = {a[2] * y_extra_scale}\n y_offset={a[3] * y_extra_scale}",
},
)
else:
Expand Down Expand Up @@ -1876,7 +1876,7 @@ def __init__(self, fit_type=1, ax=[], options={}):
ax = plt.gca()
self.ax = ax
lines = self.ax.get_lines()
if type(fit_type) == int:
if type(fit_type) is int:
self.res = {
"fit_type": [],
"fit_func": [],
Expand Down Expand Up @@ -1935,7 +1935,7 @@ def __init__(self, fit_type=1, ax=[], options={}):
self.res["x"].append(single_fit.x)
self.res["y"].append(single_fit.y)
self.res["yf"].append(single_fit.yf)
if type(fit_type) == int:
if type(fit_type) is int:
self.res["p"].append(single_fit.p)
self.res["y0"].append(single_fit.y0)
self.res["x0"].append(single_fit.x0)
Expand Down Expand Up @@ -2005,7 +2005,7 @@ def __init__(self, line, fit_type=1, ax=[], options={}):
y_data / y_scale,
options["initial_guess"],
)
print(f"func = { options ['func'] }, a = {popt}")
print(f"func = {options['func']}, a = {popt}")
self.fit_func = lambda x: fit_type(x / x_scale, popt) * y_scale
(l,) = plt.plot(x_data, self.fit_func(x_data), "m", linewidth=2)
self.fit_line_obj = l
Expand All @@ -2023,7 +2023,7 @@ def __init__(self, line, fit_type=1, ax=[], options={}):
else:
pass

elif type(fit_type) == int:
elif type(fit_type) is int:
self.ok = self.fit_polygon(line, options)

else:
Expand Down
4 changes: 2 additions & 2 deletions qualang_tools/addons/calibration/calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ def _time_of_flight(self, plot=False):
plt.plot(
adc1,
"b",
label=f"TOF to add: {tof1} ns and offset to remove: {np.mean(adc1[:tof1])*1000:.4f} mV",
label=f"TOF to add: {tof1} ns and offset to remove: {np.mean(adc1[:tof1]) * 1000:.4f} mV",
)
if tof1 is not None:
plt.axvline(x=tof1, color="b", linestyle=":")
Expand All @@ -1083,7 +1083,7 @@ def _time_of_flight(self, plot=False):
plt.plot(
adc2,
"r",
label=f"TOF to add: {tof2} ns and offset to remove: {np.mean(adc2[:tof2])*1000:.4f} mV",
label=f"TOF to add: {tof2} ns and offset to remove: {np.mean(adc2[:tof2]) * 1000:.4f} mV",
)
if tof2 is not None:
plt.axvline(x=tof2, color="r", linestyle=":")
Expand Down
24 changes: 12 additions & 12 deletions qualang_tools/bakery/bakery.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ def add_op(
elif "singleInput" in self._local_config["elements"][qe]:
for i in range(len(samples)):
assert (
type(samples[i]) == float or type(samples[i]) == int
type(samples[i]) is float or type(samples[i]) is int
), f"{qe} is a singleInput element, list of numbers (int or float) should be provided "

pulse = {
Expand Down Expand Up @@ -740,10 +740,10 @@ def play(self, Op: str, qe: str, amp: Union[float, Tuple[float]] = 1.0) -> None:
Q3 = [None] * len(Q)

for i in range(len(I)):
if type(amp) == float or type(amp) == int:
if type(amp) is float or type(amp) is int:
I2[i] = amp * I[i]
Q2[i] = amp * Q[i]
elif len(amp) != 4 or type(amp) != tuple:
elif len(amp) != 4 or type(amp) is not tuple:
raise IndexError("Amplitudes provided must be stored in a tuple (v00, v01, v10, v11)")
else:
I2[i] = amp[0] * I[i] + amp[1] * Q[i]
Expand All @@ -757,7 +757,7 @@ def play(self, Op: str, qe: str, amp: Union[float, Tuple[float]] = 1.0) -> None:
elif "singleInput" in self._local_config["elements"][qe]:
for i in range(len(samples)):
assert (
type(samples[i]) == float or type(samples[i]) == int
type(samples[i]) is float or type(samples[i]) is int
), f"{qe} is a singleInput element, list of numbers (int or float) should be provided "
self._samples_dict[qe]["single"].append(amp * np.cos(freq * i * 1e-9 + phi) * samples[i])
self._update_qe_time(qe, len(samples))
Expand Down Expand Up @@ -793,8 +793,8 @@ def play_at(self, Op: str, qe: str, t: int, amp: Union[float, Tuple[float]] = 1.
"""
freq = self._qe_dict[qe]["freq"]
phi = self._qe_dict[qe]["phase"]
if type(t) != int:
if type(t) == float:
if type(t) is not int:
if type(t) is float:
t = int(t)
else:
raise TypeError("Provided time is not an integer")
Expand Down Expand Up @@ -830,11 +830,11 @@ def play_at(self, Op: str, qe: str, t: int, amp: Union[float, Tuple[float]] = 1.
[None] * len(I),
)
for i in range(len(I)):
if type(amp) == float or type(amp) == int:
if type(amp) is float or type(amp) is int:
I2[i] = amp * I[i]
Q2[i] = amp * Q[i]
else:
if len(amp) != 4 or type(amp) != tuple:
if len(amp) != 4 or type(amp) is not tuple:
raise IndexError("Amplitudes provided must be stored in a tuple (v00, v01, v10, v11)")
else:
I2[i] = amp[0] * I[i] + amp[1] * Q[i]
Expand All @@ -860,12 +860,12 @@ def play_at(self, Op: str, qe: str, t: int, amp: Union[float, Tuple[float]] = 1.
new_samples += 1

elif "singleInput" in self._local_config["elements"][qe]:
if type(amp) != float and type(amp) != int:
if type(amp) is not float and type(amp) is not int:
raise IndexError("Amplitude must be a number")

for i in range(len(samples)):
assert (
type(samples[i]) == float or type(samples[i]) == int
type(samples[i]) is float or type(samples[i]) is int
), f"{qe} is a singleInput element, list of numbers (int or float) should be provided "
if t + i < len(self._samples_dict[qe]["single"]):
self._samples_dict[qe]["single"][t + i] += (
Expand Down Expand Up @@ -1053,7 +1053,7 @@ def run(
else:
index2 = list(zip(*amp_array))[0].index(qe)
amp = list(zip(*amp_array))[1][index2]
if type(amp) == list:
if type(amp) is list:
raise TypeError("Amplitude can only be a number (either Python or QUA variable)")
qua.play(f"baked_Op_{self._ctr}" * qua.amp(amp), qe)

Expand All @@ -1073,7 +1073,7 @@ def run(
else:
index2 = list(zip(*amp_array))[0].index(qe)
amp = list(zip(*amp_array))[1][index2]
if type(amp) == list:
if type(amp) is list:
raise TypeError("Amplitude can only be a number (either Python or QUA variable)")
qua.play(f"baked_Op_{self._ctr}" * qua.amp(amp), qe, truncate=trunc)

Expand Down
2 changes: 1 addition & 1 deletion qualang_tools/config/primitive_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def info(self):
return self.controller, self.port_id

def __eq__(self, other) -> bool:
return self.info == other.info and type(self) == type(other)
return self.info == other.info and type(self) is type(other)

def __str__(self):
cont, port_id = self.info
Expand Down
2 changes: 1 addition & 1 deletion qualang_tools/digital_filters/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def _warning_on_one_line(message, category, filename, lineno, file=None, line=No
f"The feedforward taps reached the maximum value of {qop_version.value['feedforward_max']}.\n"
f"The coefficients are scaled down to stay within the valid range which reduces the outputted amplitude of"
f" the pulses played through the filtered port by a factor of "
f"{max_value/qop_version.value['feedforward_max']:.3f}."
f"{max_value / qop_version.value['feedforward_max']:.3f}."
)

return list(feedforward_taps), list(feedback_taps)
10 changes: 5 additions & 5 deletions qualang_tools/plot/fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def fit_type(x_var, a):
x_data,
y_data,
".",
label=f"a = {out['a'][0]:.1f} +/- {out['a'][1]:.1f} \n b = {out['b'][0]:.1f} +/- {out['b'][1]:.1f}",
label=f"a = {out['a'][0]:.1f} +/- {out['a'][1]:.1f} \n b = {out['b'][0]:.1f} +/- {out['b'][1]:.1f}",
)
plt.legend(loc="upper right")
# Save the data in a json file named 'id.json' if save=id
Expand Down Expand Up @@ -246,7 +246,7 @@ def fit_type(x_var, a):
x_data,
y_data,
".",
label=f"T1 = {out['T1'][0]:.1f} +/- {out['T1'][1]:.1f} {time_unit}",
label=f"T1 = {out['T1'][0]:.1f} +/- {out['T1'][1]:.1f} {time_unit}",
)
plt.legend(loc="upper right")
# Save the data in a json file named 'id.json' if save=id
Expand Down Expand Up @@ -428,7 +428,7 @@ def fit_type(x_var, a):
x_data,
y_data,
".",
label=f"T2 = {out['T2'][0]:.1f} +/- {out['T2'][1]:.1f}ns \n f = {out['f'][0] * 1000:.3f} +/- {out['f'][1] * 1000:.3f} MHz",
label=f"T2 = {out['T2'][0]:.1f} +/- {out['T2'][1]:.1f}ns \n f = {out['f'][0] * 1000:.3f} +/- {out['f'][1] * 1000:.3f} MHz",
)
plt.legend(loc="upper right")
# Save the data in a json file named 'id.json' if save=id
Expand Down Expand Up @@ -578,7 +578,7 @@ def fit_type(x_var, a):
x_data,
y_data,
".",
label=f"f = {out['f'][0]:.1f} +/- {out['f'][1]:.1f} {freq_unit}",
label=f"f = {out['f'][0]:.1f} +/- {out['f'][1]:.1f} {freq_unit}",
)
plt.xlabel(f"Frequency {freq_unit}")
plt.legend(loc="upper right")
Expand Down Expand Up @@ -751,7 +751,7 @@ def fit_type(x_var, a):
x_data,
y_data,
".",
label=f"f = {out['f'][0]:.1f} +/- {out['f'][1]:.1f} {freq_unit}",
label=f"f = {out['f'][0]:.1f} +/- {out['f'][1]:.1f} {freq_unit}",
)
plt.legend(loc="upper right")
# Save the data in a json file named 'id.json' if save=id
Expand Down
6 changes: 3 additions & 3 deletions qualang_tools/results/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def is_processing(self):
return self._b_cont or self._b_last

def _format(self, data):
if type(data) == np.ndarray:
if type(data[0]) == np.void:
if type(data) is np.ndarray:
if type(data[0]) is np.void:
if len(data.dtype) == 1:
data = data["value"]
return data
Expand Down Expand Up @@ -114,7 +114,7 @@ def progress_counter(iteration, total, progress_bar=True, percent=True, start_ti
if percent:
progress += f"{current_percent:.1f}% (n={iteration + 1}/{total})"
if start_time is not None:
progress += f" --> elapsed time: {time.time()-start_time:.2f}s"
progress += f" --> elapsed time: {time.time() - start_time:.2f}s"

print(progress, end="\r")
if current_percent == 100:
Expand Down
3 changes: 2 additions & 1 deletion qualang_tools/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def create_simulator_controller_connections(
if i + 1 in actual_controllers and j + 1 in actual_controllers:
controller_connections.append(
ControllerConnection(
InterOpxChannel(f"con{i+1}", first_con_port), InterOpxChannel(f"con{j+1}", second_con_port)
InterOpxChannel(f"con{i + 1}", first_con_port),
InterOpxChannel(f"con{j + 1}", second_con_port),
)
)
if print_debug:
Expand Down
Loading

0 comments on commit be92404

Please sign in to comment.