Commit 6275fc89 authored by Simon Sebastian Humpohl's avatar Simon Sebastian Humpohl
Browse files

Merge branch 'simon' into 'master'

New cool stuff!

See merge request !3
parents f4573d70 5c2a9782
......@@ -11,7 +11,7 @@ python setup.py develop
```
This will link the files into your environment instead of copying them. If you are on windows you can use [SourceTree](https://www.sourcetreeapp.com/) which is a nice GUI for git.
# qutil.plotting
## qutil.plotting
`cycle_plots` helps you cycling through many plots with the arrow keys (there are probably much better functions for this out there)
`plot_2d_dataframe` helps you plot 2d data frames with numeric indices
......@@ -25,3 +25,10 @@ For an overview of the included functions, see the module docstring.
## qutil.qi
In this module there are some quantities and functions related to quantum information, like the Pauli matrices in different data types.
## qutil.itertools
This module contains a everything from `itertools`, `more_itertools` and custom functions.
## qutil.caching
Here you find decorators, functions and classes that help you implement caching like `file_cache` and `lru_cache`. This is helpful if you need to call computationally expensive functions with the same arguments repeatedly.
"""Programming tools"""
import shelve
from typing import Callable, Generator, Any
import inspect
import tempfile
import os.path
import itertools
import functools
import numpy as np
from qutil.itertools import separate_iterator
__all__ = ["file_cache", "lru_cache"]
def to_key(obj: Any) -> Generator[str]:
"""Convert to a string representation that is unique except for
- lists and ndarrays are treated the same
:param obj:
:return:
"""
if isinstance(obj, tuple):
element_key_generator = itertools.chain.from_iterable(map(to_key, obj))
yield '('
yield from separate_iterator(element_key_generator, ',')
yield ',)'
elif isinstance(obj, (list, np.ndarray)):
element_key_generator = itertools.chain.from_iterable(map(to_key, obj))
yield '['
yield from separate_iterator(element_key_generator, ',')
yield ']'
elif isinstance(obj, dict):
# we need to sort the representations in the case the objects are not sortable
sorted_items = sorted(''.join(itertools.chain(to_key(key), (':',), to_key(value)))
for key, value in obj.items())
yield '{'
yield from separate_iterator(sorted_items, ',')
yield '}'
elif isinstance(obj, (set, frozenset)):
sorted_elements = sorted(map(''.join, map(to_key, obj)))
yield '{'
yield from separate_iterator(sorted_elements, ',')
yield '}'
elif isinstance(obj, (int, float, complex, str, bytes)) or obj is None:
yield repr(obj)
else:
raise TypeError('not handled: ', type(obj))
class CachingWrapper:
"""This object wraps a callable and caches the results in a dbm database on the file system (by default in the temp
folder). The key is generated via to_key which means that large arguments need a large time to process."""
def __init__(self, func, storage_path=None):
self._func = func
if storage_path is None:
storage_path = os.path.join(tempfile.gettempdir(), inspect.getmodule(func).__name__ + func.__name__)
self.storage_path = storage_path
def __call__(self, *args, **kwargs):
key = ''.join(to_key((args, kwargs)))
with shelve.open(self.storage_path) as db:
if key in db:
result = db[key]
else:
result = self._func(*args, **kwargs)
db[key] = result
return result
def clear(self):
with shelve.open(self.storage_path) as db:
db.clear()
def file_cache(func: Callable) -> Callable:
return CachingWrapper(func)
lru_cache = functools.lru_cache
"""Import everything from itertools, more_itertools and some custom functions """
from typing import Iterable, Generator, Any
from itertools import *
from more_itertools import *
def separate_iterator(it: Iterable, sep: Any) -> Generator:
"""separate_iterator('abcde', ',') --> a , b , c , d , e"""
it = iter(it)
yield from islice(it, 1)
yield from chain.from_iterable(zip(repeat(sep), it))
"""This module contains utility functions that help interacting with matlab and matlab files"""
import itertools
import numpy
import hdf5storage
import pandas
import qutil.caching
def load_special_measure_scan(file_name: str, squeeze_constant_setchan: bool = True) -> pandas.DataFrame:
"""
__all_ = ['load_special_measure_scan', 'cached_load_mat_file', 'special_measure_to_dataframe']
:param file_name: Path of the file to load
:param squeeze_constant_setchan: If true, "set channels" that are constant are not included in the index
:return: Data frame with a multi-index that corresponds to the "set channels" and columns that correspond to the
"get channels".
"""
# this is slow as the scan stuct is quite complicated and hdf5storage creates a dtype for the whole thing
file_contents = hdf5storage.loadmat(file_name)
loops = file_contents['scan']['loops'].squeeze(axis=(0, 1))
def special_measure_to_dataframe(loaded_scan_data: dict,
squeeze_constant_setchan: bool = True) -> pandas.DataFrame:
loops = loaded_scan_data['scan']['loops'].squeeze(axis=(0, 1))
n_loops = loops.shape[-1]
n_points = loops['npoints'].squeeze(axis=2).astype(numpy.int64)
......@@ -48,7 +42,7 @@ def load_special_measure_scan(file_name: str, squeeze_constant_setchan: bool = T
measured = [ch[0, 0][0, 0] for ch in getchan if all(ch.shape)]
# always vector cell
data = file_contents['data'].flatten()
data = loaded_scan_data['data'].flatten()
result = pandas.DataFrame(index=idx)
assert len(measured) == len(data)
......@@ -66,4 +60,22 @@ def load_special_measure_scan(file_name: str, squeeze_constant_setchan: bool = T
return result
def load_special_measure_scan(file_name: str,
squeeze_constant_setchan: bool = True) -> pandas.DataFrame:
"""
:param file_name: Path of the file to load
:param squeeze_constant_setchan: If true, "set channels" that are constant are not included in the index
:param use_cache:
:return: Data frame with a multi-index that corresponds to the "set channels" and columns that correspond to the
"get channels".
"""
# this is slow as the scan stuct is quite complicated and hdf5storage creates a dtype for the whole thing
file_contents = hdf5storage.loadmat(file_name)
return special_measure_to_dataframe(file_contents, squeeze_constant_setchan)
@qutil.caching.file_cache
def cached_load_mat_file(filename):
return hdf5storage.loadmat(filename)
......@@ -33,7 +33,7 @@ setup(name='qutil',
packages=find_packages(),
package_dir={'qutil': 'qutil'},
python_requires='>=3.5',
install_requires=['numpy', 'hdf5storage', 'pandas'],
install_requires=['numpy', 'hdf5storage', 'pandas', 'more-itertools'],
classifiers=[
"Programming Language :: Python :: 3",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment