Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make qualang-tools compatible with python 3.12 #249

Merged
merged 16 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading