scqubits
Advanced tools
| # Marker file for PEP 561. |
| # qubit_base.py | ||
| # | ||
| # This file is part of scqubits. | ||
| # | ||
| # Copyright (c) 2019, Jens Koch and Peter Groszkowski | ||
| # 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. | ||
| ############################################################################ | ||
| """ | ||
| Provides the base classes for qubits | ||
| """ | ||
| import functools | ||
| import inspect | ||
| from abc import ABC, abstractmethod | ||
| import matplotlib.pyplot as plt | ||
| import numpy as np | ||
| import scipy as sp | ||
| import scqubits.core.constants as constants | ||
| import scqubits.settings as settings | ||
| import scqubits.ui.qubit_widget as ui | ||
| import scqubits.utils.plotting as plot | ||
| from scqubits.core.central_dispatch import DispatchClient | ||
| from scqubits.core.discretization import Grid1d | ||
| from scqubits.core.storage import SpectrumData, DataStore | ||
| from scqubits.settings import IN_IPYTHON | ||
| from scqubits.utils.cpu_switch import get_map_method | ||
| from scqubits.utils.misc import InfoBar, drop_private_keys, process_which | ||
| from scqubits.utils.plot_defaults import set_scaling | ||
| from scqubits.utils.spectrum_utils import ( | ||
| get_matrixelement_table, | ||
| order_eigensystem, | ||
| recast_esys_mapdata, | ||
| standardize_sign, | ||
| ) | ||
| if IN_IPYTHON: | ||
| from tqdm.notebook import tqdm | ||
| else: | ||
| from tqdm import tqdm | ||
| # To facilitate warnings in set_units, introduce a counter keeping track of the number of QuantumSystem instances | ||
| _QUANTUMSYSTEM_COUNTER = 0 | ||
| # —Generic quantum system container and Qubit base class————————————————————————————————— | ||
| class QuantumSystem(DispatchClient, ABC): | ||
| """Generic quantum system class""" | ||
| # see PEP 526 https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations | ||
| truncated_dim: int | ||
| _image_filename: str | ||
| _evec_dtype: type | ||
| _sys_type: str | ||
| subclasses = [] | ||
| def __new__(cls, *args, **kwargs): | ||
| global _QUANTUMSYSTEM_COUNTER | ||
| _QUANTUMSYSTEM_COUNTER += 1 | ||
| return super().__new__(cls, *args, **kwargs) | ||
| def __del__(self): | ||
| global _QUANTUMSYSTEM_COUNTER | ||
| _QUANTUMSYSTEM_COUNTER -= 1 | ||
| def __init_subclass__(cls, **kwargs): | ||
| """Used to register all non-abstract subclasses as a list in `QuantumSystem.subclasses`.""" | ||
| super().__init_subclass__(**kwargs) | ||
| if not inspect.isabstract(cls): | ||
| cls.subclasses.append(cls) | ||
| def __repr__(self): | ||
| if hasattr(self, "_init_params"): | ||
| init_names = self._init_params | ||
| else: | ||
| init_names = list(inspect.signature(self.__init__).parameters.keys())[1:] | ||
| init_dict = {name: getattr(self, name) for name in init_names} | ||
| return type(self).__name__ + f"(**{init_dict!r})" | ||
| def __str__(self): | ||
| output = self._sys_type.upper() + "\n ———— PARAMETERS ————" | ||
| for param_name, param_val in drop_private_keys(self.__dict__).items(): | ||
| output += "\n" + str(param_name) + "\t: " + str(param_val) | ||
| output += "\nHilbert space dimension\t: " + str(self.hilbertdim()) | ||
| return output | ||
| @abstractmethod | ||
| def hilbertdim(self): | ||
| """Returns dimension of Hilbert space""" | ||
| @classmethod | ||
| def create(cls): | ||
| """Use ipywidgets to create a new class instance""" | ||
| init_params = cls.default_params() | ||
| instance = cls(**init_params) | ||
| instance.widget() | ||
| return instance | ||
| def widget(self, params=None): | ||
| """Use ipywidgets to modify parameters of class instance""" | ||
| init_params = params or self.get_initdata() | ||
| ui.create_widget( | ||
| self.set_params, init_params, image_filename=self._image_filename | ||
| ) | ||
| @staticmethod | ||
| @abstractmethod | ||
| def default_params(): | ||
| """Return dictionary with default parameter values for initialization of class instance""" | ||
| def set_params(self, **kwargs): | ||
| """ | ||
| Set new parameters through the provided dictionary. | ||
| Parameters | ||
| ---------- | ||
| kwargs: dict (str: Number) | ||
| """ | ||
| for param_name, param_val in kwargs.items(): | ||
| setattr(self, param_name, param_val) | ||
| def supported_noise_channels(self): | ||
| """ | ||
| Returns a list of noise channels this QuantumSystem supports. If none, return an empty list. | ||
| """ | ||
| return [] | ||
| # —QubitBaseClass——————————————————————————————————————————————————————————————————————————————————————————————————————— | ||
| class QubitBaseClass(QuantumSystem, ABC): | ||
| """Base class for superconducting qubit objects. Provide general mechanisms and routines | ||
| for plotting spectra, matrix elements, and writing data to files | ||
| """ | ||
| # see PEP 526 https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations | ||
| truncated_dim: int | ||
| _default_grid: Grid1d | ||
| _evec_dtype: type | ||
| _sys_type: str | ||
| _init_params: list | ||
| @abstractmethod | ||
| def hamiltonian(self): | ||
| """Returns the Hamiltonian""" | ||
| def _evals_calc(self, evals_count): | ||
| hamiltonian_mat = self.hamiltonian() | ||
| evals = sp.linalg.eigh( | ||
| hamiltonian_mat, eigvals_only=True, eigvals=(0, evals_count - 1) | ||
| ) | ||
| return np.sort(evals) | ||
| def _esys_calc(self, evals_count): | ||
| hamiltonian_mat = self.hamiltonian() | ||
| evals, evecs = sp.linalg.eigh( | ||
| hamiltonian_mat, eigvals_only=False, eigvals=(0, evals_count - 1) | ||
| ) | ||
| evals, evecs = order_eigensystem(evals, evecs) | ||
| return evals, evecs | ||
| def eigenvals(self, evals_count=6, filename=None, return_spectrumdata=False): | ||
| """Calculates eigenvalues using `scipy.linalg.eigh`, returns numpy array of eigenvalues. | ||
| Parameters | ||
| ---------- | ||
| evals_count: int | ||
| number of desired eigenvalues/eigenstates (default value = 6) | ||
| filename: str, optional | ||
| path and filename without suffix, if file output desired (default value = None) | ||
| return_spectrumdata: bool, optional | ||
| if set to true, the returned data is provided as a SpectrumData object (default value = False) | ||
| Returns | ||
| ------- | ||
| ndarray or SpectrumData | ||
| eigenvalues as ndarray or in form of a SpectrumData object | ||
| """ | ||
| evals = self._evals_calc(evals_count) | ||
| if filename or return_spectrumdata: | ||
| specdata = SpectrumData( | ||
| energy_table=evals, system_params=self.get_initdata() | ||
| ) | ||
| if filename: | ||
| specdata.filewrite(filename) | ||
| return specdata if return_spectrumdata else evals | ||
| def eigensys(self, evals_count=6, filename=None, return_spectrumdata=False): | ||
| """Calculates eigenvalues and corresponding eigenvectors using `scipy.linalg.eigh`. Returns | ||
| two numpy arrays containing the eigenvalues and eigenvectors, respectively. | ||
| Parameters | ||
| ---------- | ||
| evals_count: int, optional | ||
| number of desired eigenvalues/eigenstates (default value = 6) | ||
| filename: str, optional | ||
| path and filename without suffix, if file output desired (default value = None) | ||
| return_spectrumdata: bool, optional | ||
| if set to true, the returned data is provided as a SpectrumData object (default value = False) | ||
| Returns | ||
| ------- | ||
| tuple(ndarray, ndarray) or SpectrumData | ||
| eigenvalues, eigenvectors as numpy arrays or in form of a SpectrumData object | ||
| """ | ||
| evals, evecs = self._esys_calc(evals_count) | ||
| if filename or return_spectrumdata: | ||
| specdata = SpectrumData( | ||
| energy_table=evals, system_params=self.get_initdata(), state_table=evecs | ||
| ) | ||
| if filename: | ||
| specdata.filewrite(filename) | ||
| return specdata if return_spectrumdata else (evals, evecs) | ||
| def matrixelement_table( | ||
| self, operator, evecs=None, evals_count=6, filename=None, return_datastore=False | ||
| ): | ||
| """Returns table of matrix elements for `operator` with respect to the eigenstates of the qubit. | ||
| The operator is given as a string matching a class method returning an operator matrix. | ||
| E.g., for an instance `trm` of Transmon, the matrix element table for the charge operator is given by | ||
| `trm.op_matrixelement_table('n_operator')`. | ||
| When `esys` is set to `None`, the eigensystem is calculated on-the-fly. | ||
| Parameters | ||
| ---------- | ||
| operator: str | ||
| name of class method in string form, returning operator matrix in qubit-internal basis. | ||
| evecs: ndarray, optional | ||
| if not provided, then the necessary eigenstates are calculated on the fly | ||
| evals_count: int, optional | ||
| number of desired matrix elements, starting with ground state (default value = 6) | ||
| filename: str, optional | ||
| output file name | ||
| return_datastore: bool, optional | ||
| if set to true, the returned data is provided as a DataStore object (default value = False) | ||
| Returns | ||
| ------- | ||
| ndarray | ||
| """ | ||
| if evecs is None: | ||
| _, evecs = self.eigensys(evals_count=evals_count) | ||
| operator_matrix = getattr(self, operator)() | ||
| table = get_matrixelement_table(operator_matrix, evecs) | ||
| if filename or return_datastore: | ||
| data_store = DataStore( | ||
| system_params=self.get_initdata(), matrixelem_table=table | ||
| ) | ||
| if filename: | ||
| data_store.filewrite(filename) | ||
| return data_store if return_datastore else table | ||
| def _esys_for_paramval(self, paramval, param_name, evals_count): | ||
| setattr(self, param_name, paramval) | ||
| return self.eigensys(evals_count) | ||
| def _evals_for_paramval(self, paramval, param_name, evals_count): | ||
| setattr(self, param_name, paramval) | ||
| return self.eigenvals(evals_count) | ||
| def get_spectrum_vs_paramvals( | ||
| self, | ||
| param_name, | ||
| param_vals, | ||
| evals_count=6, | ||
| subtract_ground=False, | ||
| get_eigenstates=False, | ||
| filename=None, | ||
| num_cpus=settings.NUM_CPUS, | ||
| ): | ||
| """Calculates eigenvalues/eigenstates for a varying system parameter, given an array of parameter values. | ||
| Returns a `SpectrumData` object with `energy_data[n]` containing eigenvalues calculated for | ||
| parameter value `param_vals[n]`. | ||
| Parameters | ||
| ---------- | ||
| param_name: str | ||
| name of parameter to be varied | ||
| param_vals: ndarray | ||
| parameter values to be plugged in | ||
| evals_count: int, optional | ||
| number of desired eigenvalues (sorted from smallest to largest) (default value = 6) | ||
| subtract_ground: bool, optional | ||
| if True, eigenvalues are returned relative to the ground state eigenvalue (default value = False) | ||
| get_eigenstates: bool, optional | ||
| return eigenstates along with eigenvalues (default value = False) | ||
| filename: str, optional | ||
| file name if direct output to disk is wanted | ||
| num_cpus: int, optional | ||
| number of cores to be used for computation (default value: settings.NUM_CPUS) | ||
| Returns | ||
| ------- | ||
| SpectrumData object | ||
| """ | ||
| previous_paramval = getattr(self, param_name) | ||
| tqdm_disable = num_cpus > 1 or settings.PROGRESSBAR_DISABLED | ||
| target_map = get_map_method(num_cpus) | ||
| if get_eigenstates: | ||
| func = functools.partial( | ||
| self._esys_for_paramval, param_name=param_name, evals_count=evals_count | ||
| ) | ||
| with InfoBar( | ||
| "Parallel computation of eigenvalues [num_cpus={}]".format(num_cpus), | ||
| num_cpus, | ||
| ): | ||
| # Note that it is useful here that the outermost eigenstate object is a list, | ||
| # as for certain applications the necessary hilbert space dimension can vary with paramvals | ||
| eigensystem_mapdata = list( | ||
| target_map( | ||
| func, | ||
| tqdm( | ||
| param_vals, | ||
| desc="Spectral data", | ||
| leave=False, | ||
| disable=tqdm_disable, | ||
| ), | ||
| ) | ||
| ) | ||
| eigenvalue_table, eigenstate_table = recast_esys_mapdata( | ||
| eigensystem_mapdata | ||
| ) | ||
| else: | ||
| func = functools.partial( | ||
| self._evals_for_paramval, param_name=param_name, evals_count=evals_count | ||
| ) | ||
| with InfoBar( | ||
| "Parallel computation of eigensystems [num_cpus={}]".format(num_cpus), | ||
| num_cpus, | ||
| ): | ||
| eigenvalue_table = list( | ||
| target_map( | ||
| func, | ||
| tqdm( | ||
| param_vals, | ||
| desc="Spectral data", | ||
| leave=False, | ||
| disable=tqdm_disable, | ||
| ), | ||
| ) | ||
| ) | ||
| eigenvalue_table = np.asarray(eigenvalue_table) | ||
| eigenstate_table = None | ||
| if subtract_ground: | ||
| for param_index, _ in enumerate(param_vals): | ||
| eigenvalue_table[param_index] -= eigenvalue_table[param_index, 0] | ||
| setattr(self, param_name, previous_paramval) | ||
| specdata = SpectrumData( | ||
| eigenvalue_table, | ||
| self.get_initdata(), | ||
| param_name, | ||
| param_vals, | ||
| state_table=eigenstate_table, | ||
| ) | ||
| if filename: | ||
| specdata.filewrite(filename) | ||
| return SpectrumData( | ||
| eigenvalue_table, | ||
| self.get_initdata(), | ||
| param_name, | ||
| param_vals, | ||
| state_table=eigenstate_table, | ||
| ) | ||
| def get_matelements_vs_paramvals( | ||
| self, | ||
| operator, | ||
| param_name, | ||
| param_vals, | ||
| evals_count=6, | ||
| num_cpus=settings.NUM_CPUS, | ||
| ): | ||
| """Calculates matrix elements for a varying system parameter, given an array of parameter values. Returns a | ||
| `SpectrumData` object containing matrix element data, eigenvalue data, and eigenstate data.. | ||
| Parameters | ||
| ---------- | ||
| operator: str | ||
| name of class method in string form, returning operator matrix | ||
| param_name: str | ||
| name of parameter to be varied | ||
| param_vals: ndarray | ||
| parameter values to be plugged in | ||
| evals_count: int, optional | ||
| number of desired eigenvalues (sorted from smallest to largest) (default value = 6) | ||
| num_cpus: int, optional | ||
| number of cores to be used for computation (default value: settings.NUM_CPUS) | ||
| Returns | ||
| ------- | ||
| SpectrumData object | ||
| """ | ||
| spectrumdata = self.get_spectrum_vs_paramvals( | ||
| param_name, | ||
| param_vals, | ||
| evals_count=evals_count, | ||
| get_eigenstates=True, | ||
| num_cpus=num_cpus, | ||
| ) | ||
| paramvals_count = len(param_vals) | ||
| matelem_table = np.empty( | ||
| shape=(paramvals_count, evals_count, evals_count), dtype=np.complex_ | ||
| ) | ||
| for index, paramval in tqdm( | ||
| enumerate(param_vals), | ||
| total=len(param_vals), | ||
| disable=settings.PROGRESSBAR_DISABLED, | ||
| leave=False, | ||
| ): | ||
| evecs = spectrumdata.state_table[index] | ||
| matelem_table[index] = self.matrixelement_table( | ||
| operator, evecs=evecs, evals_count=evals_count | ||
| ) | ||
| spectrumdata.matrixelem_table = matelem_table | ||
| return spectrumdata | ||
| def plot_evals_vs_paramvals( | ||
| self, | ||
| param_name, | ||
| param_vals, | ||
| evals_count=6, | ||
| subtract_ground=None, | ||
| num_cpus=settings.NUM_CPUS, | ||
| **kwargs, | ||
| ): | ||
| """Generates a simple plot of a set of eigenvalues as a function of one parameter. | ||
| The individual points correspond to the a provided array of parameter values. | ||
| Parameters | ||
| ---------- | ||
| param_name: str | ||
| name of parameter to be varied | ||
| param_vals: ndarray | ||
| parameter values to be plugged in | ||
| evals_count: int, optional | ||
| number of desired eigenvalues (sorted from smallest to largest) (default value = 6) | ||
| subtract_ground: bool, optional | ||
| whether to subtract ground state energy from all eigenvalues (default value = False) | ||
| num_cpus: int, optional | ||
| number of cores to be used for computation (default value: settings.NUM_CPUS) | ||
| **kwargs: dict | ||
| standard plotting option (see separate documentation) | ||
| Returns | ||
| ------- | ||
| Figure, Axes | ||
| """ | ||
| specdata = self.get_spectrum_vs_paramvals( | ||
| param_name, | ||
| param_vals, | ||
| evals_count=evals_count, | ||
| subtract_ground=subtract_ground, | ||
| num_cpus=num_cpus, | ||
| ) | ||
| return plot.evals_vs_paramvals(specdata, which=range(evals_count), **kwargs) | ||
| def plot_matrixelements( | ||
| self, | ||
| operator, | ||
| evecs=None, | ||
| evals_count=6, | ||
| mode="abs", | ||
| show_numbers=False, | ||
| show3d=True, | ||
| **kwargs, | ||
| ): | ||
| """Plots matrix elements for `operator`, given as a string referring to a class method | ||
| that returns an operator matrix. E.g., for instance `trm` of Transmon, the matrix element plot | ||
| for the charge operator `n` is obtained by `trm.plot_matrixelements('n')`. | ||
| When `esys` is set to None, the eigensystem with `which` eigenvectors is calculated. | ||
| Parameters | ||
| ---------- | ||
| operator: str | ||
| name of class method in string form, returning operator matrix | ||
| evecs: ndarray, optional | ||
| eigensystem data of evals, evecs; eigensystem will be calculated if set to None (default value = None) | ||
| evals_count: int, optional | ||
| number of desired matrix elements, starting with ground state (default value = 6) | ||
| mode: str, optional | ||
| entry from MODE_FUNC_DICTIONARY, e.g., `'abs'` for absolute value (default) | ||
| show_numbers: bool, optional | ||
| determines whether matrix element values are printed on top of the plot (default: False) | ||
| show3d: bool, optional | ||
| whether to show a 3d skyscraper plot of the matrix alongside the 2d plot (default: True) | ||
| **kwargs: dict | ||
| standard plotting option (see separate documentation) | ||
| Returns | ||
| ------- | ||
| Figure, Axes | ||
| """ | ||
| matrixelem_array = self.matrixelement_table(operator, evecs, evals_count) | ||
| if not show3d: | ||
| return plot.matrix2d( | ||
| matrixelem_array, mode=mode, show_numbers=show_numbers, **kwargs | ||
| ) | ||
| return plot.matrix( | ||
| matrixelem_array, mode=mode, show_numbers=show_numbers, **kwargs | ||
| ) | ||
| def plot_matelem_vs_paramvals( | ||
| self, | ||
| operator, | ||
| param_name, | ||
| param_vals, | ||
| select_elems=4, | ||
| mode="abs", | ||
| num_cpus=settings.NUM_CPUS, | ||
| **kwargs, | ||
| ): | ||
| """Generates a simple plot of a set of eigenvalues as a function of one parameter. | ||
| The individual points correspond to the a provided array of parameter values. | ||
| Parameters | ||
| ---------- | ||
| operator: str | ||
| name of class method in string form, returning operator matrix | ||
| param_name: str | ||
| name of parameter to be varied | ||
| param_vals: ndarray | ||
| parameter values to be plugged in | ||
| select_elems: int or list, optional | ||
| either maximum index of desired matrix elements, or list [(i1, i2), (i3, i4), ...] of index tuples | ||
| for specific desired matrix elements (default value = 4) | ||
| mode: str, optional | ||
| entry from MODE_FUNC_DICTIONARY, e.g., `'abs'` for absolute value (default value = 'abs') | ||
| num_cpus: int, optional | ||
| number of cores to be used for computation (default value = 1) | ||
| **kwargs: dict | ||
| standard plotting option (see separate documentation) | ||
| Returns | ||
| ------- | ||
| Figure, Axes | ||
| """ | ||
| if isinstance(select_elems, int): | ||
| evals_count = select_elems | ||
| else: | ||
| flattened_list = [index for tupl in select_elems for index in tupl] | ||
| evals_count = max(flattened_list) + 1 | ||
| specdata = self.get_matelements_vs_paramvals( | ||
| operator, param_name, param_vals, evals_count=evals_count, num_cpus=num_cpus | ||
| ) | ||
| return plot.matelem_vs_paramvals( | ||
| specdata, select_elems=select_elems, mode=mode, **kwargs | ||
| ) | ||
| def set_and_return(self, attr_name, value): | ||
| """ | ||
| Allows to set an attribute after which self is returned. This is useful for doing | ||
| something like example:: | ||
| qubit.set_and_return('flux', 0.23).some_method() | ||
| instead of example:: | ||
| qubit.flux=0.23 | ||
| qubit.some_method() | ||
| Parameters | ||
| ---------- | ||
| attr_name: str | ||
| name of class attribute in string form | ||
| value: any | ||
| value that the attribute is to be set to | ||
| Returns | ||
| ------- | ||
| self | ||
| """ | ||
| setattr(self, attr_name, value) | ||
| return self | ||
| # —QubitBaseClass1d————————————————————————————————————————————————————————————————————————————————————————————————————— | ||
| class QubitBaseClass1d(QubitBaseClass): | ||
| """Base class for superconducting qubit objects with one degree of freedom. Provide general mechanisms and routines | ||
| for plotting spectra, matrix elements, and writing data to files. | ||
| """ | ||
| # see PEP 526 https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations | ||
| _evec_dtype = np.float_ | ||
| _default_grid: Grid1d | ||
| @abstractmethod | ||
| def potential(self, phi): | ||
| pass | ||
| @abstractmethod | ||
| def wavefunction(self, esys, which=0, phi_grid=None): | ||
| pass | ||
| @abstractmethod | ||
| def wavefunction1d_defaults(self, mode, evals, wavefunc_count): | ||
| pass | ||
| def plot_wavefunction( | ||
| self, which=0, mode="real", esys=None, phi_grid=None, scaling=None, **kwargs | ||
| ): | ||
| """Plot 1d phase-basis wave function(s). Must be overwritten by higher-dimensional qubits like FluxQubits and | ||
| ZeroPi. | ||
| Parameters | ||
| ---------- | ||
| esys: (ndarray, ndarray), optional | ||
| eigenvalues, eigenvectors | ||
| which: int or tuple or list, optional | ||
| single index or tuple/list of integers indexing the wave function(s) to be plotted. | ||
| If which is -1, all wavefunctions up to the truncation limit are plotted. | ||
| phi_grid: Grid1d, optional | ||
| used for setting a custom grid for phi; if None use self._default_grid | ||
| mode: str, optional | ||
| choices as specified in `constants.MODE_FUNC_DICT` (default value = 'abs_sqr') | ||
| scaling: float or None, optional | ||
| custom scaling of wave function amplitude/modulus | ||
| **kwargs: dict | ||
| standard plotting option (see separate documentation) | ||
| Returns | ||
| ------- | ||
| Figure, Axes | ||
| """ | ||
| fig_ax = kwargs.get("fig_ax") or plt.subplots() | ||
| kwargs["fig_ax"] = fig_ax | ||
| index_list = process_which(which, self.truncated_dim) | ||
| if esys is None: | ||
| evals_count = max(index_list) + 2 | ||
| esys = self.eigensys(evals_count) | ||
| evals, _ = esys | ||
| phi_grid = phi_grid or self._default_grid | ||
| potential_vals = self.potential(phi_grid.make_linspace()) | ||
| evals_count = len(index_list) | ||
| if evals_count == 1: | ||
| scale = set_scaling(self, scaling, potential_vals) | ||
| else: | ||
| scale = 0.75 * (evals[-1] - evals[0]) / evals_count | ||
| amplitude_modifier = constants.MODE_FUNC_DICT[mode] | ||
| kwargs = { | ||
| **self.wavefunction1d_defaults(mode, evals, wavefunc_count=len(index_list)), | ||
| **kwargs, | ||
| } | ||
| # in merging the dictionaries in the previous line: if any duplicates, later ones survive | ||
| for wavefunc_index in index_list: | ||
| phi_wavefunc = self.wavefunction( | ||
| esys, which=wavefunc_index, phi_grid=phi_grid | ||
| ) | ||
| phi_wavefunc.amplitudes = standardize_sign(phi_wavefunc.amplitudes) | ||
| phi_wavefunc.amplitudes = amplitude_modifier(phi_wavefunc.amplitudes) | ||
| plot.wavefunction1d( | ||
| phi_wavefunc, | ||
| potential_vals=potential_vals, | ||
| offset=phi_wavefunc.energy, | ||
| scaling=scale, | ||
| **kwargs, | ||
| ) | ||
| return fig_ax |
@@ -7,2 +7,2 @@ h5py>=2.10 | ||
| traitlets | ||
| typing_extensions | ||
| typing_extensions |
+18
-2
| Metadata-Version: 2.1 | ||
| Name: scqubits | ||
| Version: 4.0.0 | ||
| Version: 4.1.0 | ||
| Summary: scqubits: superconducting qubits in Python | ||
@@ -25,7 +25,23 @@ Home-page: https://scqubits.readthedocs.io | ||
| Requires-Python: >=3.7 | ||
| License-File: LICENSE | ||
| Requires-Dist: cycler | ||
| Requires-Dist: cython>=0.29.20 | ||
| Requires-Dist: matplotlib>=3.5.1 | ||
| Requires-Dist: numpy>=1.14.2 | ||
| Requires-Dist: qutip>=4.3.1; python_version >= "3.9" | ||
| Requires-Dist: qutip<5.0; python_version < "3.9" | ||
| Requires-Dist: scipy>=1.5 | ||
| Requires-Dist: dill | ||
| Requires-Dist: sympy | ||
| Requires-Dist: tqdm | ||
| Requires-Dist: typing_extensions | ||
| Provides-Extra: graphics | ||
| Requires-Dist: matplotlib-label-lines>=0.3.6; extra == "graphics" | ||
| Provides-Extra: explorer | ||
| Requires-Dist: ipywidgets>=7.5; extra == "explorer" | ||
| Provides-Extra: h5-support | ||
| Requires-Dist: h5py>=2.10; extra == "h5-support" | ||
| Provides-Extra: pathos | ||
| License-File: LICENSE | ||
| Requires-Dist: pathos; extra == "pathos" | ||
| Requires-Dist: dill; extra == "pathos" | ||
@@ -32,0 +48,0 @@ |
+4
-3
| cycler | ||
| cython>=0.29.20,<3.0.0 | ||
| matplotlib>=3.5 | ||
| cython>=0.29.20 | ||
| matplotlib>=3.5.1 | ||
| numpy>=1.14.2 | ||
| qutip>=4.3.1 | ||
| qutip>=4.3.1; python_version >= "3.9" | ||
| qutip<5.0; python_version < "3.9" | ||
| scipy>=1.5 | ||
@@ -7,0 +8,0 @@ dill |
| Metadata-Version: 2.1 | ||
| Name: scqubits | ||
| Version: 4.0.0 | ||
| Version: 4.1.0 | ||
| Summary: scqubits: superconducting qubits in Python | ||
@@ -25,7 +25,23 @@ Home-page: https://scqubits.readthedocs.io | ||
| Requires-Python: >=3.7 | ||
| License-File: LICENSE | ||
| Requires-Dist: cycler | ||
| Requires-Dist: cython>=0.29.20 | ||
| Requires-Dist: matplotlib>=3.5.1 | ||
| Requires-Dist: numpy>=1.14.2 | ||
| Requires-Dist: qutip>=4.3.1; python_version >= "3.9" | ||
| Requires-Dist: qutip<5.0; python_version < "3.9" | ||
| Requires-Dist: scipy>=1.5 | ||
| Requires-Dist: dill | ||
| Requires-Dist: sympy | ||
| Requires-Dist: tqdm | ||
| Requires-Dist: typing_extensions | ||
| Provides-Extra: graphics | ||
| Requires-Dist: matplotlib-label-lines>=0.3.6; extra == "graphics" | ||
| Provides-Extra: explorer | ||
| Requires-Dist: ipywidgets>=7.5; extra == "explorer" | ||
| Provides-Extra: h5-support | ||
| Requires-Dist: h5py>=2.10; extra == "h5-support" | ||
| Provides-Extra: pathos | ||
| License-File: LICENSE | ||
| Requires-Dist: pathos; extra == "pathos" | ||
| Requires-Dist: dill; extra == "pathos" | ||
@@ -32,0 +48,0 @@ |
| cycler | ||
| cython<3.0.0,>=0.29.20 | ||
| matplotlib>=3.5 | ||
| cython>=0.29.20 | ||
| matplotlib>=3.5.1 | ||
| numpy>=1.14.2 | ||
| qutip>=4.3.1 | ||
| scipy>=1.5 | ||
@@ -12,2 +11,8 @@ dill | ||
| [:python_version < "3.9"] | ||
| qutip<5.0 | ||
| [:python_version >= "3.9"] | ||
| qutip>=4.3.1 | ||
| [explorer] | ||
@@ -14,0 +19,0 @@ ipywidgets>=7.5 |
@@ -8,2 +8,4 @@ LICENSE | ||
| scqubits/__init__.py | ||
| scqubits/py.typed | ||
| scqubits/qubit_base_OLD.py | ||
| scqubits/settings.py | ||
@@ -10,0 +12,0 @@ scqubits/testing.py |
@@ -81,3 +81,3 @@ import pyparsing as pp | ||
| UNITS = {name: Opt(PREFIX, None) for name in energy_names} | ||
| UNITS["EJ"] += UNITS_FREQ_ENERGY ^ Literal("A") # Ampere | ||
| UNITS["EJ"] += UNITS_FREQ_ENERGY ^ Literal("A") ^ Literal("H") # Ampere, Henry | ||
| UNITS["EC"] += UNITS_FREQ_ENERGY ^ Literal("F") # Farad | ||
@@ -84,0 +84,0 @@ UNITS["EL"] += UNITS_FREQ_ENERGY ^ Literal("H") # Henry |
+45
-22
@@ -22,2 +22,3 @@ # diag.py | ||
| import numpy as np | ||
| import qutip as q | ||
| import scipy as sp | ||
@@ -71,12 +72,21 @@ import scqubits.settings as settings | ||
| """ | ||
| Casts a given matrix into a required form ('sparse' or 'dense') | ||
| as defined by `cast_to` parameter. | ||
| Note that in some cases casting may not be explicitly needed, | ||
| for example: the sparse matrix routines can can often accept | ||
| dense matrices. The parameter `force_cast` determines if the | ||
| casing should be always done, or only where it is necessary. | ||
| Casts a given operator (possibly given as a `Qobj`) into a | ||
| required form ('sparse' or 'dense' numpy array or scipy martrix) as | ||
| defined by `cast_to` parameter. | ||
| Operators of the type `Qobj` are first converted to a `ndarray` or a | ||
| scipy sparse matrix form (depending on the given object's underlying | ||
| `dtype`). | ||
| Later those are converted (or not) to a dense or spare forms depending | ||
| on whether `force_cast` is set. | ||
| NOTE: Currently we only ever cast to the csc format for sparse | ||
| matrices. Internally `Qobj` uses the csr or dia formats instead, however. | ||
| It could be worthwhile to also use those representations directly | ||
| whenever it makes sense, and avoid unnecessary conversions. | ||
| Parameters | ||
| ---------- | ||
| matrix: Qobj, ndarray or csc_matrx | ||
| matrix: `Qobj`, `ndarray` or scipy's sparse matrix format | ||
| matrix given as an ndarray, Qobj, or scipy's sparse matrix format | ||
@@ -86,24 +96,37 @@ cast_to: str | ||
| force_cast: bool | ||
| determines of casting should be always performed or only where necessary | ||
| determines if explicit casting to dense or sparse format should be always | ||
| performed | ||
| Returns | ||
| ---------- | ||
| matrix in the right sparse or dense form | ||
| matrix in the sparse or dense form | ||
| """ | ||
| if cast_to not in ["sparse", "dense"]: | ||
| raise ValueError("Can only cast matrix to 'sparse' or 'dense' forms.") | ||
| m = matrix | ||
| if cast_to == "sparse": | ||
| if isinstance(matrix, Qobj): | ||
| m = csc_matrix(matrix.data) | ||
| elif force_cast and isinstance(matrix, ndarray): | ||
| m = csc_matrix(matrix) | ||
| # First, if we are dealing with a Qobj, we convert it to either | ||
| # an ndarray or a scipy sparse matrix. | ||
| if isinstance(matrix, Qobj): | ||
| if q.__version__ >= "5.0.0": | ||
| if matrix.dtype == q.core.data.dense.Dense: | ||
| m = matrix.full() | ||
| else: | ||
| # This could be costly if the data is in a "Dia" | ||
| # form. In the future we may want to support other | ||
| # formats as well. | ||
| m = matrix.to("CSR").as_data() | ||
| else: | ||
| # In previous versions of qutip data was always in the csr form | ||
| m = matrix.data | ||
| elif cast_to == "dense": | ||
| if isinstance(matrix, Qobj): | ||
| m = matrix.full() | ||
| elif force_cast and sp.sparse.issparse(matrix): | ||
| m = matrix.toarray() | ||
| else: | ||
| raise ValueError("Can only matrix to 'sparse' or 'dense' forms.") | ||
| # Next, we do casting dense or sparse (CSC) representation | ||
| # if force_cast is True | ||
| if force_cast: | ||
| if cast_to == "dense" and not isinstance(m, ndarray): | ||
| m = m.toarray() | ||
| if cast_to == "sparse": | ||
| m = csc_matrix(m) | ||
@@ -139,3 +162,3 @@ return m | ||
| for i in range(evecs_count): | ||
| v = Qobj(evecs[:, i], dims=evec_dims, type="ket") | ||
| v = Qobj(evecs[:, i], dims=evec_dims) | ||
| evecs_qobj[i] = v / v.norm() | ||
@@ -142,0 +165,0 @@ |
@@ -446,2 +446,3 @@ # hilbert_space.py | ||
| self._out_of_sync = False | ||
| self._out_of_sync_warning_issued = False | ||
| # end attributes for compatibility with SpectrumLookupMixin | ||
@@ -833,7 +834,7 @@ | ||
| """ | ||
| bare_hamiltonian = ( | ||
| qt.Qobj(0, dims=[self.subsystem_dims] * 2) | ||
| if qt.__version__ >= "5.0.0" | ||
| else qt.Qobj(0) | ||
| # We create a dimension [1] system if no subsystems have been given | ||
| bare_hamiltonian = qt.qzero( | ||
| [1] if len(self.subsystem_dims) == 0 else self.subsystem_dims | ||
| ) | ||
| for subsys_index, subsys in enumerate(self): | ||
@@ -865,6 +866,5 @@ if bare_esys is not None and subsys_index in bare_esys: | ||
| if not self.interaction_list: | ||
| return ( | ||
| qt.Qobj(0, dims=[self.subsystem_dims] * 2) | ||
| if qt.__version__ >= "5.0.0" | ||
| else qt.Qobj(0) | ||
| # We return a dimension [1] system if no subsystems have been given | ||
| return qt.qzero( | ||
| [1] if len(self.subsystem_dims) == 0 else self.subsystem_dims | ||
| ) | ||
@@ -871,0 +871,0 @@ |
@@ -140,4 +140,2 @@ # explorer_widget.py | ||
| utils.check_matplotlib_compatibility() | ||
| # == GUI elements ========================================================= | ||
@@ -144,0 +142,0 @@ self.ui: Dict[str, Any] = {} |
@@ -31,14 +31,9 @@ # fileio_qutip.py | ||
| """ | ||
| qobj_dims = io_data.ndarrays["qobj_dims"] | ||
| # Qobj in Qutip>=5 wants this to be a nested list | ||
| qobj_dims = io_data.ndarrays["qobj_dims"].tolist() | ||
| qobj_shape = io_data.ndarrays["qobj_shape"] | ||
| evec_array = io_data.ndarrays["evecs"] | ||
| qt_eigenstates = np.asarray( | ||
| [ | ||
| ( | ||
| qt.Qobj(evec, type="ket") | ||
| if qt.__version__ >= "5.0.0" | ||
| else qt.Qobj(evec, dims=qobj_dims, shape=qobj_shape, type="ket") | ||
| ) | ||
| for evec in evec_array | ||
| ], | ||
| [qt.Qobj(evec, dims=qobj_dims) for evec in evec_array], | ||
| dtype=np.dtype("O"), | ||
@@ -45,0 +40,0 @@ ) |
@@ -20,3 +20,2 @@ # misc.py | ||
| from collections.abc import Sequence | ||
| from distutils.version import StrictVersion | ||
| from io import StringIO | ||
@@ -488,12 +487,2 @@ from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union | ||
| def check_matplotlib_compatibility(): | ||
| if _HAS_WIDGET_BACKEND and StrictVersion(matplotlib.__version__) < StrictVersion( | ||
| "3.5.1" | ||
| ): | ||
| warnings.warn( | ||
| "The widget backend requires Matplotlib >=3.5.1 for proper functioning", | ||
| UserWarning, | ||
| ) | ||
| def inspect_public_API( | ||
@@ -500,0 +489,0 @@ module: Any, |
| # THIS FILE IS GENERATED FROM scqubits SETUP.PY | ||
| short_version = '4.0.0' | ||
| version = '4.0.0' | ||
| short_version = '4.1.0' | ||
| version = '4.1.0' | ||
| release = True |
+1
-1
@@ -56,3 +56,3 @@ """scqubits: superconducting qubits in Python | ||
| MAJOR = 4 | ||
| MINOR = 0 | ||
| MINOR = 1 | ||
| MICRO = 0 | ||
@@ -59,0 +59,0 @@ ISRELEASED = True |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
8665490
0.32%143
1.42%31415
1.95%