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

Enable Precommit hook (darker/linting) and Updates to Docs #110

Merged
merged 22 commits into from
Jun 29, 2022
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
16 changes: 16 additions & 0 deletions .github/workflows/darker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Lint with Darker

on: [push, pull_request]

jobs:
lint-with-darker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.0.2
with:
fetch-depth: 0
- uses: akaihola/darker@1.5.0
with:
options: "--check --diff"
src: "./broadbean"
revision: "origin/master..."
6 changes: 4 additions & 2 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ jobs:
- name: Build docs on linux
run: |
cd docs
make -f Makefile execute
export SPHINXOPTS="-W -v"
make html
if: runner.os == 'Linux'
- name: Build docs on windows
run: |
cd docs
./execute_notebooks.cmd
$env:SPHINXOPTS = "-W -v"
./make.bat html
if: runner.os == 'Windows'
- name: Upload build docs
uses: actions/upload-artifact@v3.1.0
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,4 @@ cython_debug/
.vscode/

# Mac files
.DS_Store
.DS_Store
24 changes: 24 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-ast
- id: check-json
- id: check-toml
- id: check-yaml
- id: debug-statements
- id: mixed-line-ending
args: ['--fix=no']
- repo: https://github.com/asottile/pyupgrade
rev: v2.32.1
hooks:
- id: pyupgrade
args: ['--py37-plus', '--keep-runtime-typing']
- repo: https://github.com/akaihola/darker
rev: 1.5.0
hooks:
- id: darker
args: [-i]
additional_dependencies: [isort]
39 changes: 5 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
[ ![PyPI python versions](https://img.shields.io/pypi/pyversions/broadbean.svg) ](https://pypi.python.org/pypi/broadbean/)
[ ![Build Status Github](https://github.com/QCoDeS/broadbean/workflows/Run%20mypy%20and%20pytest/badge.svg) ](https://github.com/QCoDeS/broadbean/actions?query=workflow%3A%22Run+mypy+and+pytest%22)

A library for making pulses. Supposed to be used with QCoDeS (in
particular its Tektronix AWG 5014 driver), but works as standalone.
A library for making pulses that can be leveraged with QCoDeS (in
particular its Tektronix AWG 5014 driver), but also works as standalone.

The usage is documented in the jupyter notebooks found in the `docs` folder.
The usage is documented in example notebooks TODO: add link to hosted docs.

Short description: The broadbean module lets the user compose and
manipulate pulse sequences. The aim of the module is to reduce pulse
Expand All @@ -26,37 +26,8 @@ The name: The broad bean is one of my favourite pulses.

### Formal requirements

The broadbean package only works with python 3.6+
The broadbean package only works with python 3.7+

### Installation

On a good day, installation is as easy as
```
$ git clone https://github.com/QCoDeS/broadbean.git bbdir
$ cd bbdir
$ pip install .
```
behind the scenes, `numpy`, `matplotlib`, and `PyQt5` are installed if
not found. If `pip` failed you, you may need to run it as root. But a
better idea is to use a [virtual enviroment](https://github.com/pyenv/pyenv-virtualenv).

You can now fire up a python 3 interpreter and go
```
>>> import broadbean as bb
>>> from broadbean import ripasso as rp
```

### Documentation

Apart from the example notebooks, auto-generated documentation is
available. As for now, the user must built it herself, but that is
luckily easy.

In the `bbdir` folder, do:
```
$ pip install -r docs_requirements.txt
$ cd docs
$ make html
```
then ignore all warnings and just have a look at the file `bbdir/docs/build/html/index.html`.

TODO: add link to installation from docs
6 changes: 3 additions & 3 deletions broadbean/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# flake8: noqa (ignore unused imports)

# Version 1.0

from . import ripasso
from ._version import __version__
from .blueprint import BluePrint
from .broadbean import PulseAtoms
from .element import Element
from .sequence import Sequence
from .blueprint import BluePrint
from .tools import makeVaryingSequence, repeatAndVarySequence
from .broadbean import PulseAtoms
44 changes: 26 additions & 18 deletions broadbean/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ def _make_names_unique(lst):
for ii, ind in enumerate(inds):
# Do not append numbers to the first occurence
if ii == 0:
lst[ind] = '{}'.format(un)
lst[ind] = f"{un}"
else:
lst[ind] = '{}{}'.format(un, ii+1)
lst[ind] = f"{un}{ii+1}"

return lst

Expand Down Expand Up @@ -240,7 +240,7 @@ def description(self):
no_segs = len(self._namelist)

for sn in range(no_segs):
segkey = 'segment_{:02d}'.format(sn+1)
segkey = f"segment_{sn+1:02d}"
desc[segkey] = {}
desc[segkey]['name'] = self._namelist[sn]
if self._funlist[sn] == 'waituntil':
Expand Down Expand Up @@ -284,9 +284,11 @@ def blueprint_from_description(cls, blue_dict):
blue_dict: a dict in the same form as returned by
BluePrint.description
"""
knowfunctions = dict([('function PulseAtoms.{}'.format(fun),
getattr(PulseAtoms, fun)) for fun in
dir(PulseAtoms) if '__' not in fun])
knowfunctions = {
f"function PulseAtoms.{fun}": getattr(PulseAtoms, fun)
for fun in dir(PulseAtoms)
if "__" not in fun
}
seg_mar_list = list(blue_dict.keys())
seg_list = [s for s in seg_mar_list if 'segment' in s]
bp_sum = cls()
Expand Down Expand Up @@ -322,7 +324,7 @@ def init_from_json(cls, path_to_file: str) -> 'BluePrint':
The JSON file needs to be structured as if it was writen
by the function write_to_json
"""
with open(path_to_file, 'r') as fp:
with open(path_to_file) as fp:
data_loaded = json.load(fp)
return cls.blueprint_from_description(data_loaded)

Expand Down Expand Up @@ -353,9 +355,11 @@ def _makeWaitDurations(self):
wait_time = argslist[pos][0]
dur = wait_time - elapsed_time
if dur < 0:
raise ValueError('Inconsistent timing. Can not wait until ' +
'{} at position {}.'.format(wait_time, pos) +
' {} elapsed already'.format(elapsed_time))
raise ValueError(
"Inconsistent timing. Can not wait until "
+ f"{wait_time} at position {pos}."
+ f" {elapsed_time} elapsed already"
)
else:
durations[pos] = dur

Expand Down Expand Up @@ -441,10 +445,12 @@ def changeArg(self, name, arg, value, replaceeverywhere=False):
# Each function has two 'secret' arguments, SR and dur
user_params = len(sig.parameters)-2
if isinstance(arg, int) and (arg not in range(user_params)):
raise ValueError('No argument {} '.format(arg) +
'of function {}.'.format(function.__name__) +
' Has {} '.format(user_params) +
'arguments.')
raise ValueError(
f"No argument {arg} "
+ f"of function {function.__name__}."
+ f" Has {user_params} "
+ "arguments."
)

# allow the user to input single values instead of (val,)
no_of_args = len(self._argslist[position])
Expand Down Expand Up @@ -669,7 +675,7 @@ def removeSegment(self, name):
try:
position = self._namelist.index(name)
except ValueError:
raise KeyError('No segment called {} in blueprint.'.format(name))
raise KeyError(f"No segment called {name} in blueprint.")

del self._funlist[position]
del self._argslist[position]
Expand Down Expand Up @@ -799,9 +805,11 @@ def _subelementBuilder(blueprint: BluePrint, SR: int,
wait_time = argslist[pos][0]
dur = wait_time - elapsed_time
if dur < 0:
raise ValueError('Inconsistent timing. Can not wait until ' +
'{} at position {}.'.format(wait_time, pos) +
' {} elapsed already'.format(elapsed_time))
raise ValueError(
"Inconsistent timing. Can not wait until "
+ f"{wait_time} at position {pos}."
+ f" {elapsed_time} elapsed already"
)
else:
durations[pos] = dur

Expand Down
22 changes: 12 additions & 10 deletions broadbean/broadbean.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,27 @@ def gaussian(ampl, sigma, mu, offset, SR, npts):
"""
dur = npts/SR
time = np.linspace(0, dur, int(npts), endpoint=False)
centre = dur/2
baregauss = np.exp((-(time-mu-centre)**2/(2*sigma**2)))
return ampl*baregauss+offset
centre = dur / 2
baregauss = np.exp(-((time - mu - centre) ** 2) / (2 * sigma**2))
return ampl * baregauss + offset

@staticmethod
def gaussian_smooth_cutoff(ampl, sigma, mu, offset, SR, npts):
"""
Returns a Gaussian of peak height ampl (when offset==0)

Is by default centred in the middle of the interval

smooth cutoff by making offsetting the Gaussian so endpoint = 0 and normalizing the hight to 1
smooth cutoff by making offsetting the Gaussian so endpoint = 0 and normalizing the hight to 1
"""
dur = npts/SR
time = np.linspace(0, dur, int(npts), endpoint=False)
centre = dur/2
baregauss = np.exp((-(time-mu-centre)**2/(2*sigma**2)))-np.exp((-(0-mu-centre)**2/(2*sigma**2)))
normalization = 1/(1.0-np.exp((-(0-mu-centre)**2/(2*sigma**2))))
return ampl*baregauss/normalization+offset
centre = dur / 2
baregauss = np.exp(-((time - mu - centre) ** 2) / (2 * sigma**2)) - np.exp(
-((0 - mu - centre) ** 2) / (2 * sigma**2)
)
normalization = 1 / (1.0 - np.exp(-((0 - mu - centre) ** 2) / (2 * sigma**2)))
return ampl * baregauss / normalization + offset


def marked_for_deletion(replaced_by: Union[str, None]=None) -> Callable:
Expand Down Expand Up @@ -155,7 +157,7 @@ def __getitem__(self, key):

return output
else:
raise KeyError('{} is not a valid key.'.format(key))
raise KeyError(f"{key} is not a valid key.")

if isinstance(key, slice):
start = key.start
Expand Down
14 changes: 7 additions & 7 deletions broadbean/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ def init_from_json(cls, path_to_file: str) -> 'Element':
The JSON file needs to be structured as if it was writen
by the function write_to_json
"""
with open(path_to_file, 'r') as fp:
with open(path_to_file) as fp:
data_loaded = json.load(fp)
return cls.element_from_description(data_loaded)
return cls.element_from_description(data_loaded)

def changeArg(self, channel: Union[str, int],
name: str, arg: Union[str, int], value: Union[int, float],
Expand Down Expand Up @@ -335,8 +335,8 @@ def changeArg(self, channel: Union[str, int],
if channel not in self.channels:
raise ValueError(f'Nothing assigned to channel {channel}')

if 'blueprint' not in self._data[channel].keys():
raise ValueError('No blueprint on channel {}.'.format(channel))
if "blueprint" not in self._data[channel].keys():
raise ValueError(f"No blueprint on channel {channel}.")

bp = self._data[channel]['blueprint']

Expand All @@ -363,8 +363,8 @@ def changeDuration(self, channel: Union[str, int], name: str,
if channel not in self.channels:
raise ValueError(f'Nothing assigned to channel {channel}')

if 'blueprint' not in self._data[channel].keys():
raise ValueError('No blueprint on channel {}.'.format(channel))
if "blueprint" not in self._data[channel].keys():
raise ValueError(f"No blueprint on channel {channel}.")

bp = self._data[channel]['blueprint']

Expand All @@ -386,7 +386,7 @@ def _applyDelays(self, delays: List[float]) -> None:
raise ValueError('Incorrect number of delays specified.'
' Must match the number of channels.')

if not sum([d >= 0 for d in delays]) == len(delays):
if not sum(d >= 0 for d in delays) == len(delays):
raise ValueError('Negative delays not allowed.')

# The strategy is:
Expand Down
6 changes: 3 additions & 3 deletions broadbean/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@ def update_minmax(chanminmax, wfmdata, chanind):

# labels
if pos == 0:
ax.set_ylabel('({})'.format(voltageunit))
if pos == seqlen - 1 and not(isinstance(obj_to_plot, BluePrint)):
ax.set_ylabel(f"({voltageunit})")
if pos == seqlen - 1 and not (isinstance(obj_to_plot, BluePrint)):
newax = ax.twinx()
newax.set_yticks([])
if isinstance(chan, int):
Expand All @@ -299,7 +299,7 @@ def update_minmax(chanminmax, wfmdata, chanind):
if seq[pos+1]['type'] == 'subsequence':
ax.set_xlabel('Time N/A')
else:
ax.set_xlabel('({})'.format(timeunit))
ax.set_xlabel(f"({timeunit})")

# remove excess space from the plot
if not chanind+1 == len(chans):
Expand Down
Loading