diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..eb3dd6f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,47 @@
+name: ci
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+ workflow_dispatch:
+
+concurrency:
+ # cancel previous runs of this workflow (only for the same pull request, not for main)
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.9]
+ # os: [ubuntu-latest, macOS-latest, windows-latest]
+ os: [ubuntu-latest]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+ cache: "pip"
+ cache-dependency-path: "pyproject.toml"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -e ".[dev]"
+
+ - name: List installed dependencies
+ run: python -m pip list
+
+ - name: Run CI checks
+ run: task ci
diff --git a/.github/workflows/publish-doc.yml b/.github/workflows/publish-doc.yml
new file mode 100644
index 0000000..ec0dd2f
--- /dev/null
+++ b/.github/workflows/publish-doc.yml
@@ -0,0 +1,43 @@
+name: publish-doc
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+concurrency:
+ # cancel previous runs of this workflow
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up Python 3.10
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
+ cache: "pip"
+ cache-dependency-path: "pyproject.toml"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -e ".[dev]"
+
+ - name: List installed dependencies
+ run: python -m pip list
+
+ - name: Build Docs
+ run: mkdocs build
+
+ - name: Publish website
+ run: mkdocs gh-deploy --force
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..9e7130c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,79 @@
+# Contributing to floquet
+
+We welcome your contribution, whether it be additional cost functions, new functionality, better documentation, etc.
+
+## Requirements
+
+The project was written using Python 3.10+, you must have a compatible version of Python (i.e. >= 3.10) installed on your computer.
+
+## Setup
+
+Clone the repository:
+
+```shell
+git clone git@github.com:dkweiss31/floquet.git
+cd floquet
+```
+
+It is good practice to use a virtual environment to install the dependencies, such as conda. Once this environment has been activated, you can run
+
+```shell
+pip install -e .
+```
+
+to install the package and its dependencies. As a developer you also need to install the developer dependencies:
+
+```shell
+pip install -e ".[dev]"
+```
+
+## Code style
+
+This project follows PEP8 and uses automatic formatting and linting tools to ensure that the code is compliant.
+
+## Workflow
+
+### Before submitting a pull request (run all tasks)
+
+Run all tasks before each commit:
+
+```shell
+task all
+```
+
+### Build the documentation
+
+The documentation is built using [MkDocs](https://www.mkdocs.org/) and the [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) theme. MkDocs generates a static website based on the markdown files in the `docs/` directory.
+
+To preview the changes to the documentation as you edit the docstrings or the markdown files in `docs/`, we recommend starting a live preview server, which will automatically rebuild the website upon modifications:
+
+```shell
+task docserve
+```
+
+Open in your web browser to preview the documentation website.
+
+You can build the static documentation website locally with:
+
+```shell
+task docbuild
+```
+
+This will create a `site/` directory with the contents of the documentation website. You can then simply open `site/index.html` in your web browser to view the documentation website.
+
+### Run specific tasks
+
+You can also execute tasks individually:
+
+```shell
+> task --list
+lint lint the code (ruff)
+format auto-format the code (ruff)
+codespell check for misspellings (codespell)
+clean clean the code (ruff + codespell)
+test run the unit tests suite (pytest)
+docbuild build the documentation website
+docserve preview documentation website with hot-reloading
+all run all tasks before a commit (ruff + codespell + pytest)
+ci run all the CI checks
+```
diff --git a/docs/_static/custom_css.css b/docs/_static/custom_css.css
new file mode 100644
index 0000000..cd62b6e
--- /dev/null
+++ b/docs/_static/custom_css.css
@@ -0,0 +1,167 @@
+/* Fix /page#foo going to the top of the viewport and being hidden by the navbar */
+html {
+ scroll-padding-top: 50px;
+}
+
+/* Fit the Twitter handle alongside the GitHub one in the top right. */
+
+div.md-header__source {
+ width: revert;
+ max-width: revert;
+}
+
+a.md-source {
+ display: inline-block;
+}
+
+.md-source__repository {
+ max-width: 100%;
+}
+
+/* Emphasise sections of nav on left hand side */
+
+nav.md-nav {
+ padding-left: 5px;
+}
+
+nav.md-nav--secondary {
+ border-left: revert !important;
+}
+
+.md-nav__title {
+ font-size: 0.9rem;
+}
+
+.md-nav__item--section > .md-nav__link {
+ font-size: 0.9rem;
+}
+
+/* Indent autogenerated documentation */
+
+div.doc-contents {
+ padding-left: 25px;
+ border-left: 4px solid rgba(230, 230, 230);
+}
+
+/* Increase visibility of splitters "---" */
+
+[data-md-color-scheme="default"] .md-typeset hr {
+ border-bottom-color: rgb(0, 0, 0);
+ border-bottom-width: 1pt;
+}
+
+[data-md-color-scheme="slate"] .md-typeset hr {
+ border-bottom-color: rgb(230, 230, 230);
+}
+
+/* More space at the bottom of the page */
+
+.md-main__inner {
+ margin-bottom: 1.5rem;
+}
+
+/* Remove prev/next footer buttons */
+
+.md-footer__inner {
+ display: none;
+}
+
+/* Change font sizes */
+
+html {
+ /* Decrease font size for overall webpage
+ Down from 137.5% which is the Material default */
+ font-size: 110%;
+}
+
+.md-typeset .admonition {
+ /* Increase font size in admonitions */
+ font-size: 100% !important;
+}
+
+.md-typeset details {
+ /* Increase font size in details */
+ font-size: 100% !important;
+}
+
+.md-typeset h1 {
+ font-size: 1.6rem;
+}
+
+.md-typeset h2 {
+ font-size: 1.5rem;
+}
+
+.md-typeset h3 {
+ font-size: 1.3rem;
+}
+
+.md-typeset h4 {
+ font-size: 1.1rem;
+}
+
+.md-typeset h5 {
+ font-size: 0.9rem;
+}
+
+.md-typeset h6 {
+ font-size: 0.8rem;
+}
+
+/* Bugfix: remove the superfluous parts generated when doing:
+
+??? Blah
+
+ ::: library.something
+*/
+
+.md-typeset details .mkdocstrings > h4 {
+ display: none;
+}
+
+.md-typeset details .mkdocstrings > h5 {
+ display: none;
+}
+
+/* Change default colours for tags */
+
+[data-md-color-scheme="default"] {
+ --md-typeset-a-color: rgb(0, 189, 164) !important;
+}
+[data-md-color-scheme="slate"] {
+ --md-typeset-a-color: rgb(0, 189, 164) !important;
+}
+
+/* Highlight functions, classes etc. type signatures. Really helps to make clear where
+ one item ends and another begins. */
+
+[data-md-color-scheme="default"] {
+ --doc-heading-color: #DDD;
+ --doc-heading-border-color: #CCC;
+ --doc-heading-color-alt: #F0F0F0;
+}
+[data-md-color-scheme="slate"] {
+ --doc-heading-color: rgb(25,25,33);
+ --doc-heading-border-color: rgb(25,25,33);
+ --doc-heading-color-alt: rgb(33,33,44);
+ --md-code-bg-color: rgb(38,38,50);
+}
+
+h4.doc-heading {
+ /* NOT var(--md-code-bg-color) as that's not visually distinct from other code blocks.*/
+ background-color: var(--doc-heading-color);
+ border: solid var(--doc-heading-border-color);
+ border-width: 1.5pt;
+ border-radius: 2pt;
+ padding: 0pt 5pt 2pt 5pt;
+}
+h5.doc-heading, h6.heading {
+ background-color: var(--doc-heading-color-alt);
+ border-radius: 2pt;
+ padding: 0pt 5pt 2pt 5pt;
+}
+
+/* Make errors in notebooks have scrolling */
+.output_error > pre {
+ overflow: auto;
+}
diff --git a/docs/examples/transmon.ipynb b/docs/examples/transmon.ipynb
new file mode 100644
index 0000000..96bbcef
--- /dev/null
+++ b/docs/examples/transmon.ipynb
@@ -0,0 +1,346 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Transmon Floquet analysis\n",
+ "\n",
+ "Here we perform a Floquet simulation of a transmon subject to off-resonant drives. We extract as a function of drive strength and drive frequency the probability of ionization for the two qubit states. We then compare the 2D plots (with the x and y axes drive frequency and induced ac stark shift on the qubit, respectively and the z axis ionization probability) with Blais-style branch crossing plots, which identify the states the qubit states leak to."
+ ],
+ "metadata": {
+ "collapsed": false
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
+ "id": "68ebc2fd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "import qutip as qt\n",
+ "import scqubits as scq\n",
+ "\n",
+ "from cycler import cycler\n",
+ "\n",
+ "import floquet as ft\n",
+ "\n",
+ "color_cycler = plt.rcParams['axes.prop_cycle']\n",
+ "ls_cycler = cycler(ls=['-', '--', '-.', ':'])\n",
+ "alpha_cycler = cycler(alpha=[1.0, 0.6, 0.2])\n",
+ "color_ls_alpha_cycler = alpha_cycler * ls_cycler * color_cycler"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f5c02996",
+ "metadata": {},
+ "source": [
+ "## Define simulation parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "fde5cfeb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filepath = ft.generate_file_path('h5py', 'transmon_floquet', 'out')\n",
+ "\n",
+ "# drive frequencies to scan over\n",
+ "omega_d_linspace = 2.0 * np.pi * np.linspace(7.5, 10.0, 120)\n",
+ "# induced ac stark shifts to scan over\n",
+ "chi_ac_linspace = np.linspace(0.0, 0.1, 59)\n",
+ "\n",
+ "num_states = 20\n",
+ "qubit_params = {'EJ': 20.0, 'EC': 0.2, 'ng': 0.25, 'ncut': 41}\n",
+ "tmon = scq.Transmon(**qubit_params, truncated_dim=num_states)\n",
+ "state_indices = [0, 1] # get data for ground and first excited states\n",
+ "\n",
+ "# express operators in eigenbasis of transmon\n",
+ "hilbert_space = scq.HilbertSpace([tmon])\n",
+ "hilbert_space.generate_lookup()\n",
+ "evals = hilbert_space['evals'][0][0:num_states]\n",
+ "H0 = 2.0 * np.pi * qt.Qobj(np.diag(evals - evals[0]))\n",
+ "H1 = hilbert_space.op_in_dressed_eigenbasis(tmon.n_operator)\n",
+ "\n",
+ "# to achieve same range of chi_ac for the various drive frequencies,\n",
+ "# need to drive at different strengths\n",
+ "chi_to_amp = ft.ChiacToAmp(H0, H1, state_indices, omega_d_linspace)\n",
+ "# resulting array has shape (a,w), where a is amplitude and w is frequency\n",
+ "amp_linspace = chi_to_amp.amplitudes_for_omega_d(chi_ac_linspace)\n",
+ "\n",
+ "options = ft.Options(\n",
+ " fit_range_fraction=0.5, # split the fit into segments based on this fraction\n",
+ " floquet_sampling_time_fraction=0.0, # what part of the period to look at\n",
+ " fit_cutoff=4, # polynomial cutoff\n",
+ " overlap_cutoff=0.8, # cutoff for the excluding from the fit\n",
+ " nsteps=30_000, # qutip integration parameter\n",
+ " num_cpus=6,\n",
+ " save_floquet_mode_data=False, # don't save floquet modes\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "7fb27b941602401d91542211134fc71a",
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running floquet simulation with parameters: \n",
+ "fit_range_fraction: 0.5\n",
+ "floquet_sampling_time_fraction: 0.0\n",
+ "fit_cutoff: 4\n",
+ "overlap_cutoff: 0.8\n",
+ "nsteps: 30000\n",
+ "num_cpus: 6\n",
+ "save_floquet_mode_data: False\n",
+ "state_indices: [0, 1]\n",
+ "omega_d_linspace: [47.1238898 47.2558895 47.38788919 47.51988888 47.65188857 47.78388826\n",
+ " 47.91588795 48.04788764 48.17988733 48.31188703 48.44388672 48.57588641\n",
+ " 48.7078861 48.83988579 48.97188548 49.10388517 49.23588487 49.36788456\n",
+ " 49.49988425 49.63188394 49.76388363 49.89588332 50.02788301 50.1598827\n",
+ " 50.2918824 50.42388209 50.55588178 50.68788147 50.81988116 50.95188085\n",
+ " 51.08388054 51.21588023 51.34787993 51.47987962 51.61187931 51.743879\n",
+ " 51.87587869 52.00787838 52.13987807 52.27187777 52.40387746 52.53587715\n",
+ " 52.66787684 52.79987653 52.93187622 53.06387591 53.1958756 53.3278753\n",
+ " 53.45987499 53.59187468 53.72387437 53.85587406 53.98787375 54.11987344\n",
+ " 54.25187314 54.38387283 54.51587252 54.64787221 54.7798719 54.91187159\n",
+ " 55.04387128 55.17587097 55.30787067 55.43987036 55.57187005 55.70386974\n",
+ " 55.83586943 55.96786912 56.09986881 56.23186851 56.3638682 56.49586789\n",
+ " 56.62786758 56.75986727 56.89186696 57.02386665 57.15586634 57.28786604\n",
+ " 57.41986573 57.55186542 57.68386511 57.8158648 57.94786449 58.07986418\n",
+ " 58.21186388 58.34386357 58.47586326 58.60786295 58.73986264 58.87186233\n",
+ " 59.00386202 59.13586171 59.26786141 59.3998611 59.53186079 59.66386048\n",
+ " 59.79586017 59.92785986 60.05985955 60.19185925 60.32385894 60.45585863\n",
+ " 60.58785832 60.71985801 60.8518577 60.98385739 61.11585708 61.24785678\n",
+ " 61.37985647 61.51185616 61.64385585 61.77585554 61.90785523 62.03985492\n",
+ " 62.17185462 62.30385431 62.435854 62.56785369 62.69985338 62.83185307]\n",
+ "amp_linspace: [[ 0. 0. 0. ... 0. 0.\n",
+ " 0. ]\n",
+ " [ 1.12426412 1.1338659 1.14344842 ... 2.14500354 2.15300056\n",
+ " 2.16098688]\n",
+ " [ 1.58994957 1.60352853 1.61708027 ... 3.0334931 3.04480259\n",
+ " 3.05609696]\n",
+ " ...\n",
+ " [ 8.4132223 8.48507542 8.55678449 ... 16.05173669 16.1115809\n",
+ " 16.17134508]\n",
+ " [ 8.48800797 8.5604998 8.63284629 ... 16.1944216 16.25479777\n",
+ " 16.3150932 ]\n",
+ " [ 8.56214045 8.63526541 8.70824376 ... 16.33586028 16.39676376\n",
+ " 16.4575858 ]]\n",
+ "num_states: 20\n",
+ "num_fit_ranges: 2\n",
+ "num_amp_pts_per_range: 29\n",
+ "exp_pair_map: {0: (0, 1), 1: (1, 0), 2: (0, 2), 3: (1, 1), 4: (2, 0), 5: (0, 3), 6: (1, 2), 7: (2, 1), 8: (3, 0), 9: (1, 3), 10: (2, 2), 11: (3, 1)}\n",
+ "calculating for amp_range_idx=0\n",
+ "calculating for amp_range_idx=1\n",
+ "finished floquet main in 0.5436457713445028 minutes\n"
+ ]
+ }
+ ],
+ "source": [
+ "floquet_analysis = ft.floquet_analysis(\n",
+ " H0,\n",
+ " H1,\n",
+ " state_indices=state_indices,\n",
+ " omega_d_linspace=omega_d_linspace,\n",
+ " amp_linspace=amp_linspace,\n",
+ " options=options,\n",
+ ")\n",
+ "floquet_analysis.run(filepath=filepath)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3ddf2651",
+ "metadata": {},
+ "source": [
+ "## Plot the probability of nonlinear transitions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "acae54e37e7d407bbb7b55eff062a284",
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "data_dict, param_dict = ft.extract_info_from_h5(filepath)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "c8d0ce12",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "