diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml
new file mode 100644
index 0000000..4af235e
--- /dev/null
+++ b/.github/workflows/publish_to_pypi.yml
@@ -0,0 +1,184 @@
+name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
+
+on: push
+
+jobs:
+ build:
+ name: Build distribution 📦
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Fetch all history for all tags and branches
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.x"
+ - name: Install pypa/build
+ run: >-
+ python3 -m
+ pip install
+ build
+ --user
+ - name: Build a binary wheel and a source tarball
+ run: python3 -m build
+ - name: Store the distribution packages
+ uses: actions/upload-artifact@v3
+ with:
+ name: python-package-distributions
+ path: dist/
+
+
+ test-installation:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ python-version: ["3.10"]
+ steps:
+ - uses: actions/checkout@v2
+ name: Checkout the repository
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install Linux System Dependencies
+ if: startsWith(matrix.os, 'ubuntu')
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libegl1-mesa # missing libEGL.so.1
+ sudo apt-get install -y xvfb # GUI backend for matplotlib (Ubuntu doesn't have a display)
+
+ - name: Install dependencies and QFit
+ run: |
+ pip install --upgrade pip
+ pip install .
+
+ - name: Test installation on Linux
+ if: startsWith(matrix.os, 'ubuntu')
+ run: |
+ xvfb-run --auto-servernum python -c "from qfit import Fit; print('Installation successful')"
+
+ - name: Test installation on macOS and Windows
+ if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'windows')
+ run: python -c "from qfit import Fit; print('Installation successful')"
+
+
+ publish-to-pypi:
+ name: >-
+ Publish to PyPI
+ if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
+ needs:
+ - build
+ runs-on: ubuntu-latest
+ environment:
+ name: pypi
+ url: https://pypi.org/p/qfit
+ permissions:
+ id-token: write # IMPORTANT: mandatory for trusted publishing
+
+ steps:
+ - name: Download all the dists
+ uses: actions/download-artifact@v3
+ with:
+ name: python-package-distributions
+ path: dist/
+ - name: Publish distribution 📦 to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_API_TOKEN }}
+
+
+ github-release:
+ name: >-
+ Sign with Sigstore and upload them to GitHub Release
+ needs:
+ - publish-to-pypi
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: write # IMPORTANT: mandatory for making GitHub Releases
+ id-token: write # IMPORTANT: mandatory for sigstore
+
+ steps:
+ - name: Download all the dists
+ uses: actions/download-artifact@v3
+ with:
+ name: python-package-distributions
+ path: dist/
+ - name: Sign the dists with Sigstore
+ uses: sigstore/gh-action-sigstore-python@v1.2.3
+ with:
+ inputs: >-
+ ./dist/*.tar.gz
+ ./dist/*.whl
+ - name: Create GitHub Release
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ run: >-
+ gh release create
+ '${{ github.ref_name }}'
+ --repo '${{ github.repository }}'
+ --notes ""
+ - name: Upload artifact signatures to GitHub Release
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ # Upload to GitHub Release using the `gh` CLI.
+ # `dist/` contains the built packages, and the
+ # sigstore-produced signatures and certificates.
+ run: >-
+ gh release upload
+ '${{ github.ref_name }}' dist/**
+ --repo '${{ github.repository }}'
+
+
+ publish-to-testpypi:
+ name: Publish to TestPyPI
+ needs:
+ - build
+ runs-on: ubuntu-latest
+
+ environment:
+ name: testpypi
+ url: https://test.pypi.org/p/qfit
+
+ permissions:
+ contents: write # Typical permission needed for operations affecting repository contents
+
+ steps:
+ - name: Download all the dists
+ uses: actions/download-artifact@v3
+ with:
+ name: python-package-distributions
+ path: dist/
+
+ - name: Extract version from distribution 📦 file
+ # assuming the version is in the format ` \n",
" \n",
- "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`QFit` automatically detects candidate axes that are stored in the h5 file, however you need to tell `QFit` which axes are for the x-axis (the input DC voltages on flux bias lines in our case), and which axis is for the y-axis (the frequency). Since both $V_1$ and $V_2$ are swept in the two datasets, we specify `voltage_1` and `voltage_2` as x coordinates and \"frequency\" as the y coordinate. \n", + "\n", + " \n", + "
\n", "\n", - "#### 1.3 Configuring the data\n", - "Although `QFit` automatically detects the compatible x and y coordinates, as shown in the METADATA panel, you need to tell `QFit` what are ones that are actually used during the fitting. In this case, we specify \"voltage\" as the only x coordinate and \"frequency\" as the y coordinate. \n", + "Then you will see the figures oriented correctly.\n", "\n", - " \n", + " \n", "
\n", "\n", "There are a few things to note:\n", @@ -95,11 +180,68 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Calibrate flux crosstalk\n", + "## 2. Calibrate flux crosstalk" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In our example, voltages of the input DC sources for the two flux bias lines both can contribute to the external flux of the fluxonium $\\Phi_{\\text{ext}}$:\n", "\n", - "To be completed soon..." + "$$\n", + "\\Phi_{\\text{ext}} = \\alpha_1 V_1 + \\alpha_2 V_2 + \\beta .\n", + "$$\n", + "\n", + "To fully calibrate the relation between the voltages $V_1$, $V_2$ and the external flux $\\Phi_{\\text{ext}}$, we have to determine $\\alpha_1$, $\\alpha_2$ and $\\beta$. One such way to calibrate for these coefficients is to perform two two-tone spectroscopies that sweep along two (non-colinear) lines in the $(V_1, V_2)$ space.\n", + "Since we have three unknowns, we have to provide three sets of $(V_1, V_2, \\Phi_{\\text{ext}})$. Labelling them as $(V_1^{(i)}, V_2^{(i)}, \\Phi_{\\text{ext}}^{(i)})$, with $i = 1,2,3$, we end up with three linear equations:\n", + "$$\n", + "\\Phi_{\\text{ext}}^{(1)} = \\alpha_1 V_1^{(1)} + \\alpha_2 V_2^{(1)} + \\beta \\\\\n", + "\\Phi_{\\text{ext}}^{(2)} = \\alpha_1 V_1^{(2)} + \\alpha_2 V_2^{(2)} + \\beta \\\\\n", + "\\Phi_{\\text{ext}}^{(3)} = \\alpha_1 V_1^{(3)} + \\alpha_2 V_2^{(3)} + \\beta .\n", + "$$\n", + "\n", + "This also explains why we need two two-tone sweeps that are not co-linear: we need the above three equations not linearly-dependent, so that we can obtain a unique solution to those coefficients. This is only possible if we pick up three $(V_1, V_2)$ coordinates that are not all the same line. \n", + "\n", + "The CALIBRATE step helps you identify three such points. We can see in the ct1 figure there are two sweet spots that looks like $\\Phi_{\\text{ext}} = 0$ and $0.5$, then we extract $(V_1, V_2)$ at these sweet spots and then provide the corresponding external flux values:\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "and the third point is obtained from the ct2 figure:\n", + "\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then you successfully calibrate for the relation between voltages and the external flux. The calibration for circuits with multiple tuning knobs can be performed in a similar way in `QFit`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Please notice that the extracted data points for these two figures are grouped separately:\n", + "\n", + " \n", + "
\n", + "\n", + " \n", + "
" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/example_data/joint_qubit_twotone_ct2.h5 b/example_data/joint_qubit_twotone_ct2.h5 index 18cd025..cf3ba40 100644 Binary files a/example_data/joint_qubit_twotone_ct2.h5 and b/example_data/joint_qubit_twotone_ct2.h5 differ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a20bb3f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[build-system] +requires = ["setuptools>=64", "wheel", "setuptools_scm>=8"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "qfit/version.py" +version_scheme = "post-release" +local_scheme = "no-local-version" +fallback_version = "0.0" + +[project] +name = "qfit" +description = "qfit: data extraction GUI tool for use with scQubits" +readme = "README.md" +dynamic = ["version"] +authors = [ + { name = "Tianpu Zhao", email = "tianpuzhao2022@u.northwestern.edu" }, + { name = "Danyang Chen", email = "danyangchen2026@u.northwestern.edu" }, + { name = "Jens Koch", email = "jens-koch@northwestern.edu" } +] +license = { file = "LICENSE" } +keywords = ["parameter extraction", "superconducting qubits"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering", + "Operating System :: MacOS", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: Microsoft :: Windows" +] +requires-python = ">=3.10" +dependencies = [ + "numpy >= 1.14.2", + "scipy >= 1.1.0", + "matplotlib >= 3.1.2", + "pyside6", + "h5py >= 2.7.1", + "qutip < 5.0.0", + "scikit-image", + "scqubits >= 3.0.0", + "matplotlib-label-lines", + "ipykernel", + "jupyter", + "pathos", + "dill" +] + +[project.urls] +homepage = "https://github.com/scqubits/qfit" +Repository = "https://github.com/scqubits/qfit" diff --git a/qfit/__init__.py b/qfit/__init__.py index 0d36d1e..662dfa1 100644 --- a/qfit/__init__.py +++ b/qfit/__init__.py @@ -11,6 +11,7 @@ import scqubits as scq from qfit.core.qfit import Fit +from qfit.version import __version__, __version_tuple__ scq.settings.PROGRESSBAR_DISABLED = True diff --git a/qfit/models/measurement_data.py b/qfit/models/measurement_data.py index 3b7925d..503f955 100644 --- a/qfit/models/measurement_data.py +++ b/qfit/models/measurement_data.py @@ -514,7 +514,7 @@ def _addPixelCoord(self): """ Add pixel coordinates as the last resort for x and y axis candidates. """ - ydim, xdim = self._principalZ.data.shape + ydim, xdim = self._principalZ.data.shape[:2] self.xCandidates.update({f"range({xdim})": np.arange(xdim)}) self.yCandidates.update({f"range({ydim})": np.arange(ydim)}) diff --git a/qfit/views/__init__.py b/qfit/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/resources/images/adv_tip_calibrate_1.png b/resources/images/adv_tip_calibrate_1.png new file mode 100644 index 0000000..bba65e9 Binary files /dev/null and b/resources/images/adv_tip_calibrate_1.png differ diff --git a/resources/images/adv_tip_calibrate_2.png b/resources/images/adv_tip_calibrate_2.png new file mode 100644 index 0000000..c9d3686 Binary files /dev/null and b/resources/images/adv_tip_calibrate_2.png differ diff --git a/resources/images/adv_tip_correct_orientation.png b/resources/images/adv_tip_correct_orientation.png new file mode 100644 index 0000000..86cc700 Binary files /dev/null and b/resources/images/adv_tip_correct_orientation.png differ diff --git a/resources/images/adv_tip_extract_1.png b/resources/images/adv_tip_extract_1.png new file mode 100644 index 0000000..908e7b0 Binary files /dev/null and b/resources/images/adv_tip_extract_1.png differ diff --git a/resources/images/adv_tip_extract_2.png b/resources/images/adv_tip_extract_2.png new file mode 100644 index 0000000..ae98456 Binary files /dev/null and b/resources/images/adv_tip_extract_2.png differ diff --git a/resources/images/adv_tip_init_fig.png b/resources/images/adv_tip_init_fig.png new file mode 100644 index 0000000..150d121 Binary files /dev/null and b/resources/images/adv_tip_init_fig.png differ diff --git a/resources/images/adv_tip_metadata.png b/resources/images/adv_tip_metadata.png new file mode 100644 index 0000000..6af2bb9 Binary files /dev/null and b/resources/images/adv_tip_metadata.png differ diff --git a/resources/images/adv_tip_select_axes.png b/resources/images/adv_tip_select_axes.png new file mode 100644 index 0000000..cf9e948 Binary files /dev/null and b/resources/images/adv_tip_select_axes.png differ diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..a9ae438 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,7 @@ +[options] +packages = find: +exclude = + resources* + example_data* + danyang_tests* + media_raw_source* diff --git a/setup.py b/setup.py deleted file mode 100644 index c628d2b..0000000 --- a/setup.py +++ /dev/null @@ -1,152 +0,0 @@ -"""qfit: data extraction GUI tool for use with scQuibts -============================================================== - -qfit is part of scQubits, an an open-source Python package for simulating superconducting qubits. The qfit package -provides a GUI tool for loading and displaying data, for example from spectroscopy experiments. The GUI simplifies the -extraction of data points from measurement results, as required for fitting experimental data to theoretical qubit -models. -""" - -# -# This file is part of qfit. -# -# Copyright (c) 2023, Tianpu Zhao, Danyang Chen, Jens Koch -# All rights reserved. -# -# This source code is licensed under the BSD-style license found in the -# LICENSE file in the root directory of this source tree. -############################################################################ - -import os -import sys - -import setuptools - -DOCLINES = __doc__.split("\n") - -CLASSIFIERS = """\ -Development Status :: 4 - Beta -Intended Audience :: Science/Research -License :: OSI Approved :: BSD License -Programming Language :: Python -Programming Language :: Python :: 3 -Topic :: Scientific/Engineering -Operating System :: MacOS -Operating System :: POSIX -Operating System :: Unix -Operating System :: Microsoft :: Windows -""" - - -EXTRA_KWARGS = {} - - -# all information about scqubits goes here -MAJOR = 2 -MINOR = 0 -MICRO = 1 -ISRELEASED = True - - -VERSION = "%d.%d.%d" % (MAJOR, MINOR, MICRO) - -CURDIR = os.path.dirname(os.path.abspath(__file__)) -with open(os.path.join(CURDIR, "requirements.txt")) as requirements: - INSTALL_REQUIRES = requirements.read().splitlines() - -PACKAGES = [ - "qfit", - "qfit/core", - "qfit/controllers", - "qfit/models", - "qfit/ui_designer", - "qfit/utils", - "qfit/views", - "qfit/widgets", -] - -PYTHON_VERSION = ">=3.10" - - -NAME = "qfit" -AUTHOR = "Tianpu Zhao, Danyang Chen, Jens Koch" -AUTHOR_EMAIL = "jens-koch@northwestern.edu" -LICENSE = "BSD" -DESCRIPTION = DOCLINES[0] -LONG_DESCRIPTION = "\n".join(DOCLINES[2:]) -KEYWORDS = "parameter extraction, superconducting qubits" - -# URL = "https://scqubits.readthedocs.io" - -CLASSIFIERS = [_f for _f in CLASSIFIERS.split("\n") if _f] -PLATFORMS = ["Linux", "Mac OSX", "Unix", "Windows"] - - -def git_short_hash(): - try: - git_str = "+" + os.popen('git log -1 --format="%h"').read().strip() - except OSError: - git_str = "" - else: - if git_str == "+": # fixes setuptools PEP issues with versioning - git_str = "" - return git_str - - -FULLVERSION = VERSION -if not ISRELEASED: - FULLVERSION += ".dev" + str(MICRO) + git_short_hash() - - -def write_version_py(filename="qfit/version.py"): - cnt = """\ -# THIS FILE IS GENERATED FROM qfit SETUP.PY -short_version = '%(version)s' -version = '%(fullversion)s' -release = %(isrelease)s -""" - versionfile = open(filename, "w") - try: - versionfile.write( - cnt - % { - "version": VERSION, - "fullversion": FULLVERSION, - "isrelease": str(ISRELEASED), - } - ) - finally: - versionfile.close() - - -local_path = os.path.dirname(os.path.abspath(sys.argv[0])) -os.chdir(local_path) -sys.path.insert(0, local_path) -sys.path.insert(0, os.path.join(local_path, "qfit")) # to retrieve version - -# always rewrite _version -if os.path.exists("qfit/version.py"): - os.remove("qfit/version.py") - -write_version_py() - -# Setup commands go here -setuptools.setup( - name=NAME, - version=FULLVERSION, - packages=PACKAGES, - author=AUTHOR, - author_email=AUTHOR_EMAIL, - license=LICENSE, - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - keywords=KEYWORDS, - # url=URL, - classifiers=CLASSIFIERS, - platforms=PLATFORMS, - zip_safe=False, - include_package_data=True, - install_requires=INSTALL_REQUIRES, - python_requires=PYTHON_VERSION, - **EXTRA_KWARGS -)