diff --git a/.gitattributes b/.gitattributes index 1bccc1fa..201c7c94 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ *.h5 filter=lfs diff=lfs merge=lfs -text +*.aps2 filter=lfs diff=lfs merge=lfs -text +*.aps1 filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index fcfad9a8..7150e5b0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ *.h5 *.py~ *.py# +*.egg-info +QGL.egg-info/ diff --git a/.travis.yml b/.travis.yml index 6e781a45..d8a7fa46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,10 @@ language: python python: - - 3.5 + - 3.6 +env: + - CONDA_TYPE=miniconda CONDA_VERS=https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh + - CONDA_TYPE=miniconda CONDA_VERS=https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh before_install: # install git lfs and fetch test data @@ -22,11 +25,11 @@ install: # We do this conditionally because it saves us some downloading if the # version is the same. - - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; + - echo "Using $CONDA_TYPE" + - wget $CONDA_VERS -O miniconda.sh + - bash miniconda.sh -h | sed '4q;d' - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - - export BBN_MEAS_FILE="$PWD/tests/test_measure.yml" - - echo "Measure file at $BBN_MEAS_FILE" - hash -r - conda config --set always_yes yes --set changeps1 no - conda update -q conda @@ -34,10 +37,12 @@ install: - conda info -a # Create conda environment with dependencies - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bokeh h5py jupyter scipy networkx future + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy sqlalchemy jupyter scipy networkx - source activate test-environment - - conda install -c ecpy atom; - - pip install watchdog coveralls + - pip install coveralls + - pip install bqplot + - pip install git+https://github.com/BBN-Q/bbndb.git + - if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then pip install pygsti; fi script: - coverage run -m unittest discover diff --git a/QGL.egg-info/PKG-INFO b/QGL.egg-info/PKG-INFO new file mode 100644 index 00000000..ac9daf85 --- /dev/null +++ b/QGL.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: QGL +Version: 2.1 +Summary: UNKNOWN +Home-page: https://github.com/BBN-Q/QGL +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/QGL.egg-info/SOURCES.txt b/QGL.egg-info/SOURCES.txt new file mode 100644 index 00000000..945e4a89 --- /dev/null +++ b/QGL.egg-info/SOURCES.txt @@ -0,0 +1,41 @@ +README.md +QGL/BlockLabel.py +QGL/ChannelLibraries.py +QGL/Channels.py +QGL/Cliffords.py +QGL/Compiler.py +QGL/ControlFlow.py +QGL/GSTTools.py +QGL/PatternUtils.py +QGL/Plotting.py +QGL/PulsePrimitives.py +QGL/PulseSequencePlotter.py +QGL/PulseSequencer.py +QGL/PulseShapes.py +QGL/Scheduler.py +QGL/TdmInstructions.py +QGL/Tomography.py +QGL/__init__.py +QGL/config.py +QGL/config_location.py +QGL/mm.py +QGL.egg-info/PKG-INFO +QGL.egg-info/SOURCES.txt +QGL.egg-info/dependency_links.txt +QGL.egg-info/requires.txt +QGL.egg-info/top_level.txt +QGL/BasicSequences/AllXY.py +QGL/BasicSequences/BlankingSweeps.py +QGL/BasicSequences/CR.py +QGL/BasicSequences/Decoupling.py +QGL/BasicSequences/Feedback.py +QGL/BasicSequences/FlipFlop.py +QGL/BasicSequences/RB.py +QGL/BasicSequences/Rabi.py +QGL/BasicSequences/SPAM.py +QGL/BasicSequences/T1T2.py +QGL/BasicSequences/__init__.py +QGL/BasicSequences/helpers.py +QGL/drivers/APS2Pattern.py +QGL/drivers/APSPattern.py +QGL/drivers/__init__.py \ No newline at end of file diff --git a/QGL.egg-info/dependency_links.txt b/QGL.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/QGL.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/QGL.egg-info/requires.txt b/QGL.egg-info/requires.txt new file mode 100644 index 00000000..2aa45f83 --- /dev/null +++ b/QGL.egg-info/requires.txt @@ -0,0 +1,6 @@ +bbndb>=0.1 +numpy>=1.11.1 +scipy>=0.17.1 +networkx>=1.11 +bqplot>=0.11.5 +sqlalchemy>=1.2.17 diff --git a/QGL.egg-info/top_level.txt b/QGL.egg-info/top_level.txt new file mode 100644 index 00000000..0e533603 --- /dev/null +++ b/QGL.egg-info/top_level.txt @@ -0,0 +1 @@ +QGL diff --git a/QGL/APS2CustomInstructions.py b/QGL/APS2CustomInstructions.py new file mode 100644 index 00000000..971bd16b --- /dev/null +++ b/QGL/APS2CustomInstructions.py @@ -0,0 +1,86 @@ +''' +Copyright 2019 Raytheon BBN Technologies + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +''' + +# Instructions for the the prototype APS2-TDM hardware. + +from .TdmInstructions import CustomInstruction, WriteAddr, Invalidate, LoadCmpVram +from .ControlFlow import LoadCmp, Call + +##custom APS OP_CODES +#APS_CLIFFORD_SET_SEED: Set 32 bit seed for random number generator +#APS_CLIFFORD_SET_OFFSET: Stores jump table starting offset +#APS_CLIFFORD_SET_SPACING: Stores jump table spacing (integer to shift left), +# including interal address representation +#APS_CLIFFORD_INVERSE_RESET: Reset inverse tracker +#APS_CLIFFORD_RAND: Choose randomly from set of 24 waveforms, +# returns starting address of jump table entry from RAM +#APS_CLIFFORD_INVERSE: Store waveform address of inverse waveform to be jumped to + +APS2_CUSTOM = {"APS_RAND": 0, + "APS_CLIFFORD_RAND": 2, + "APS_CLIFFORD_INVERSE": 6, + "APS_CLIFFORD_INVERSE_RESET": 7, + "APS_CLIFFORD_SET_SEED": 3, + "APS_CLIFFORD_SET_OFFSET": 4, + "APS_CLIFFORD_SET_SPACING": 5} + +APS2_CUSTOM_DECODE = {v: k for k, v in APS2_CUSTOM.items()} + +##Note that the expected call pattern for the randomizer is: + +# APS_CLIFFORD_RAND / APS_CLIFFORD_INVERSE +# LOADCMP +# CALL + +def RandomCliffordSetOffset(addr, offset): + return [Invalidate(addr, 0, tdm=False), + WriteAddr(addr, offset, tdm=False), + LoadCmpVram(addr, 0xFFFFFFFF, tdm=False), # + CustomInstruction("APS_CLIFFORD_SET_OFFSET", addr, 0xA), + LoadCmpVram(0xA, 0xFFFFFFFF, tdm=False)] + +def RandomCliffordSetSpacing(addr, spacing): + return [Invalidate(addr, 0, tdm=False), + WriteAddr(addr, spacing, tdm=False), + LoadCmpVram(addr, 0xFFFFFFFF, tdm=False), + CustomInstruction("APS_CLIFFORD_SET_SPACING", addr, 0xA), + LoadCmpVram(0xA, 0xFFFFFFFF, tdm=False)] + +def RandomClifford(target, addr): + return [Invalidate(addr, 0, tdm=False), + CustomInstruction("APS_CLIFFORD_RAND", 0x0, addr), + LoadCmpVram(addr, 0xFFFFFFFF, tdm=False), + Call(target, indirect=True)] + +def RandomCliffordInverse(target, addr): + return [Invalidate(addr, 0, tdm=False), + CustomInstruction("APS_CLIFFORD_INVERSE", 0x0, addr), + LoadCmpVram(addr, 0xFFFFFFFF, tdm=False), + Call(target, indirect=True)] + +def RandomCliffordInverseReset(val=0x0, addr=0xD): #for now don't use addr + return [Invalidate(addr, 0, tdm=False), + WriteAddr(addr, val, tdm=False), + LoadCmpVram(addr, 0xFFFFFFFF, tdm=False), + CustomInstruction("APS_CLIFFORD_INVERSE_RESET", addr, 0xA), + LoadCmpVram(0xA, 0xFFFFFFFF, tdm=False)] + +def RandomCliffordSeed(seed): + return [Invalidate(0xB, 0, tdm=False), + WriteAddr(0xB, seed, tdm=False), + LoadCmpVram(0xB, 0xFFFFFFFF, tdm=False), + CustomInstruction("APS_CLIFFORD_SET_SEED", 0xB, 0xA), + LoadCmpVram(0xA, 0xFFFFFFFF, tdm=False)] diff --git a/QGL/BasicSequences/Feedback.py b/QGL/BasicSequences/Feedback.py index b7833556..6efabbfe 100644 --- a/QGL/BasicSequences/Feedback.py +++ b/QGL/BasicSequences/Feedback.py @@ -124,8 +124,8 @@ def BitFlip3(data_qs, ancilla_qs, theta=None, phi=None, nrounds=1, meas_delay=1e raise Exception("Wrong number of qubits") seqs = [ DecodeSetRounds(1,0,nrounds), - Invalidate(addr=10, mask=2*nrounds), - Invalidate(addr=11, mask=0x1)] + Invalidate(10, 2*nrounds), + Invalidate(11, 0x1)] # encode single-qubit state into 3 qubits if theta and phi: @@ -153,7 +153,7 @@ def BitFlip3(data_qs, ancilla_qs, theta=None, phi=None, nrounds=1, meas_delay=1e if docals: seqs += create_cal_seqs(qubits, calRepeats) - metafile = compile_to_hardware(seqs, 'BitFlip/BitFlip') + metafile = compile_to_hardware(seqs, 'BitFlip/BitFlip', tdm_seq=True) return metafile def MajorityVoteN(qubits, nrounds, prep=[], meas_delay=1e-6, docals=False, calRepeats=2): @@ -172,9 +172,9 @@ def MajorityVoteN(qubits, nrounds, prep=[], meas_delay=1e-6, docals=False, calRe metafile : metafile path """ nqubits = len(qubits) - seqs = [MajorityMask(nrounds*nqubits), - Invalidate(addr=10, mask=nrounds*nqubits), - Invalidate(addr=11, mask=1)] + seqs = [MajorityMask(1, 0, nrounds*nqubits), + Invalidate(10, nrounds*nqubits), + Invalidate(11, 1)] if prep: seqs += [reduce(operator.mul, [X(q) for n,q in enumerate(qubits) if prep[n]])] for n in range(nrounds): @@ -187,5 +187,4 @@ def MajorityVoteN(qubits, nrounds, prep=[], meas_delay=1e-6, docals=False, calRe if docals: seqs += create_cal_seqs(qubits, calRepeats) - metafile = compile_to_hardware(seqs, 'MajorityVote/MajorityVote') - return metafile + metafile = compile_to_hardware(seqs, 'MajorityVote/MajorityVote', tdm_seq=True) diff --git a/QGL/BasicSequences/Rabi.py b/QGL/BasicSequences/Rabi.py index 3acb5329..c65028b2 100644 --- a/QGL/BasicSequences/Rabi.py +++ b/QGL/BasicSequences/Rabi.py @@ -108,6 +108,8 @@ def RabiAmp_NQubits(qubits, if docals: seqs += create_cal_seqs(qubits, calRepeats, measChans=measChans) + else: + calRepeats = 0 axis_descriptor = [ { diff --git a/QGL/BasicSequences/StarkShift.py b/QGL/BasicSequences/StarkShift.py new file mode 100644 index 00000000..070d5c50 --- /dev/null +++ b/QGL/BasicSequences/StarkShift.py @@ -0,0 +1,167 @@ +from ..PulsePrimitives import * +from ..Compiler import compile_to_hardware +from ..ChannelLibraries import EdgeFactory +from ..PulseSequencePlotter import plot_pulse_files +from .helpers import create_cal_seqs, delay_descriptor, cal_descriptor +import numpy as np +from collections.abc import Iterable +from itertools import product + +def StarkSpectroscopy(qubit, measurement, amplitude, + delay=200e-9, length=1e-6, showPlot=False): + """Stark shift spectroscopy experiment. Applies a coherent displacement + to the qubit readout cavity while doing pulsed spectroscopy. + + Args: + qubit: Qubit channel to apply spectroscopy pulse to. + + measurement: Measurement channel to apply displacement pulse to. + + amplitude: Measurement pulse amplitude(s) + + delay: Delay between end of spectroscopy pulse and start of MEAS(qubit). + + length: Total length of cavity displacement pulse. + + Returns: + metafile: Path to compiled sequence metafile. + """ + + if not isinstance(amplitude, Iterable): + amplitude = [amplitude] + + def stark_shift_pulse(amp): + pump_pulse = Utheta(measurement, amp=amp, length=length) + l1 = length - delay - qubit.pulse_params["length"] - delay + spec_pulse = Id(qubit, length=l1)+X(qubit)+Id(qubit,length=delay) + return spec_pulse*pump_pulse + + seqs = [[stark_shift_pulse(a), MEAS(qubit)] for a in amplitude] + axis_descriptor = [{ + 'name': 'Stark Shift Amplitude', + 'unit': None, + 'points': list(amplitude), + 'partition': 1 + }] + metafile = compile_to_hardware(seqs, 'StarkSpec/StarkSpec', axis_descriptor=axis_descriptor) + + if showPlot: + plot_pulse_files(metafile) + + return metafile + +def StarkEcho(qubit, measurement, amplitudes, delays, + wait=200e-9, periods=4, showPlot=False): + """Hahn echo sequence with a coherent displacement of the qubit measurement cavity. + Used to measure photon-induced dephasing. This sequence can cause a lot of cache pressure + so number of points may be limited. + + TODO: Use QGL intrinsics to reduce sequence and memory cache utilization. + + Args: + qubit: Qubit channel for Hahn echo. + + measurement: Measurement channel of qubit. + + amplitudes: Amplitude(s) of cavity displacement pulse. + + delays: Hahn echo delays - the t in 90-t-180-t-180. + + wait: Delay between end of cavity displacement pulse and start of MEAS(qubit). + + periods: Number of artificial oscillations. + + Returns: + metafile: Path to compiled sequence metafile. + """ + + if not isinstance(amplitudes, Iterable): + amplitudes = [amplitudes] + + if not isinstance(delays, Iterable): + delays = [delays] + + def echo_phase(n): + return 2*np.pi*periods/len(delays)*n + + def echo_stark(n, amp, max_delay, meas_delay=200e-9): + x_len = qubit.pulse_params["length"] + max_len = 3*x_len + 2*max_delay + meas_delay + echo_wait = max_len - (3*x_len + 2*delays[n]) + + echo_seq = Id(qubit, echo_wait) + X90(qubit) + Id(qubit, delays[n]) + \ + Y(qubit) + Id(qubit, delays[n]) + U90(qubit, echo_phase(n)) + + meas_seq = Utheta(measurement, amp=amp, length=max_len) + + return echo_seq*meas_seq + + + seqs = [[echo_stark(n, amp, np.max(delays)), Id(measurement, length=wait), MEAS(qubit)] + for n, amp in product(range(len(delays)), amplitudes)] + + axis_descriptor = [delay_descriptor(delays)] * len(amplitudes) + + metafile = compile_to_hardware(seqs, 'StarkEcho/StarkEcho', axis_descriptor=axis_descriptor) + + if showPlot: + plot_pulse_files(metafile) + + return metafile + + +def CavityPumpProbe(qubit, measurement, offsets, amplitude, + length=1e-6, wait=1e-6, showPlot=False): + """Time resolved cavity spectroscopy. Applies a coherent displacement to qubit + readout cavity while sweeping qubit spectroscopy pulse delay. Useful to measure + cavity kappa and cavity population. + + Args: + qubit: Qubit channel for spectroscopy. + + measurement: Measurement channel of qubit. + + offsets: Spectroscopy pulse offset relative to start of cavity displacement pulse. + + amplitude: Measurement pulse amplitude. + + length: Total length of cavity displacement pulse. + + wait: Delay between end of cavity displacement pulse and start of MEAS(qubit). + + Returns: + metafile: Path to compiled sequence metafile. + """ + + if not isinstance(offsets, Iterable): + offsets = [offsets] + + def cavity_probe(offset): + pump_pulse = Utheta(measurement, amp=amplitude, length=length) + x_len = qubit.pulse_params["length"] + if offset < -1*x_len: + return [X(qubit), Id(qubit, length=(-x_len-offset)), pump_pulse, Id(qubit, length=wait)] + elif offset < 0: + total_len = length-offset + pm = Id(measurement, length=offset)+pump_pulse + pq = X(qubit)+Id(qubit, length=(total_len-x_len)) + return [pm*pq, Id(qubit, length=wait)] + elif offset < length: + pq = Id(qubit, length=offset)+X(qubit)+Id(qubit, length=(length-offset-x_len)) + return [pump_pulse*pq, Id(qubit, length=wait)] + elif offset >= length: + assert offset < (length+wait), f"Wait time {wait} is too short!" + wait_len = wait - (offset-length+x_len) + return [pump_pulse, Id(qubit, length=(offset-length)), X(qubit), Id(qubit, length=wait_len)] + + seqs = [[cavity_probe(off), MEAS(qubit)] for off in offsets] + axis_descriptor = [delay_descriptor(offsets)] + metafile = compile_to_hardware(seqs, 'CavityPumpProbe/CavityPumpProbe', axis_descriptor=axis_descriptor) + + if showPlot: + plot_pulse_files(metafile) + + return metafile + + + diff --git a/QGL/BasicSequences/__init__.py b/QGL/BasicSequences/__init__.py index d05862f9..882f430e 100644 --- a/QGL/BasicSequences/__init__.py +++ b/QGL/BasicSequences/__init__.py @@ -8,3 +8,4 @@ from .CR import EchoCRPhase, EchoCRLen, EchoCRAmp, PiRabi from .AllXY import AllXY from .Feedback import Reset, BitFlip3, MajorityVoteN +from .StarkShift import StarkSpectroscopy, StarkEcho, CavityPumpProbe diff --git a/QGL/BlockLabel.py b/QGL/BlockLabel.py index 52db8b63..6725cd13 100644 --- a/QGL/BlockLabel.py +++ b/QGL/BlockLabel.py @@ -2,8 +2,10 @@ class BlockLabel(object): - def __init__(self, label): + def __init__(self, label, jump_table=False, table_size=0): self.label = label + self.jump_table = jump_table + self.table_size = table_size def __repr__(self): return self.__str__() diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index 6afb03b2..3b4b818c 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -3,10 +3,12 @@ real channels. Split from Channels.py on Jan 14, 2016. +Moved to SQLAlchemy ORM from atom 2018 Original Author: Colm Ryan +Modified By: Graham Rowlands -Copyright 2016 Raytheon BBN Technologies +Copyright 2016-2018 Raytheon BBN Technologies Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,133 +32,322 @@ import sys import os import re +import datetime import traceback import datetime import importlib -from atom.api import Atom, Str, Int, Typed +import inspect +import operator +from functools import wraps, reduce +import itertools +import numpy as np import networkx as nx -import yaml +import logging + +import bbndb -# FSEvents observer in watchdog cannot have multiple watchers of the same path -# use kqueue instead -if sys.platform == 'darwin': - from watchdog.observers.kqueue import KqueueObserver as Observer -else: - from watchdog.observers import Observer -from watchdog.events import FileSystemEventHandler -import time +from bqplot import Figure, LinearScale, Axis, Lines, Figure +from bqplot.marks import Graph, Lines, Label +from ipywidgets import Layout, VBox, HBox +from . import config from . import Channels from . import PulseShapes -from . import config +from .PulsePrimitives import clear_pulse_cache + +from IPython.display import HTML, display channelLib = None -class MyEventHandler(FileSystemEventHandler): - - def __init__(self, file_paths, callback): - super(MyEventHandler, self).__init__() - self.file_paths = [os.path.normpath(fn) for fn in file_paths] - self.callback = callback - self.paused = True - - # The spotlight indexer in MacOSX retriggers events... maybe we should hash the files? - self.grace_period = 3.0 if sys.platform == 'darwin' else 1.0 - self.last_library_update = datetime.datetime.now() - - def on_modified(self, event): - try: - if any([os.path.samefile(event.src_path, fp) for fp in self.file_paths]): - if not self.paused: - # Build in some sanity checking since we seem to get multiple - # events firing in a number of situations. - now = datetime.datetime.now() - - if (now-self.last_library_update).total_seconds() > (self.grace_period): - self.last_library_update = now - """ - Hold off for half a second - If the event is from the file being opened to be written this gives - time for it to be written. - """ - time.sleep(0.5) - self.callback() - except FileNotFoundError: - #Temporary settings files generated using yaml_dump get deleted - #faster than the above code can catch it. - pass - -class LibraryFileWatcher(object): - def __init__(self, main_path, callback): - super(LibraryFileWatcher, self).__init__() - - self.main_path = os.path.normpath(main_path) - self.callback = callback - - # Perform a preliminary loading to find all of the connected files... - # TODO: modularity - with open(os.path.abspath(self.main_path), 'r') as FID: - loader = config.Loader(FID) - try: - tmpLib = loader.get_single_data() - self.filenames = [os.path.normpath(lf) for lf in loader.filenames] - finally: - loader.dispose() - - self.eventHandler = MyEventHandler(self.filenames, self.callback) - self.observer = Observer() - self.observer.schedule(self.eventHandler, path=os.path.dirname(os.path.abspath(main_path))) - - self.observer.start() - self.resume() - - def __del__(self): - self.observer.stop() - self.observer.join() - - def pause(self): - self.eventHandler.paused = True - - def resume(self): - self.eventHandler.paused = False - -class ChannelLibrary(Atom): - # channelDict = Dict(Str, Channel) - channelDict = Typed(dict) - connectivityG = Typed(nx.DiGraph) - library_file = Str() - fileWatcher = Typed(LibraryFileWatcher) - version = Int(5) - last_library_update = Str() - - specialParams = ['phys_chan', 'gate_chan', 'trig_chan', 'receiver_chan', - 'source', 'target'] - - def __init__(self, library_file=None, blank=False, channelDict={}, **kwargs): - """Create the channel library. We assume that the user wants the config file in the - usual locations specified in the config files.""" - - # Load the basic config options from the yaml - self.library_file = config.load_config(library_file) - - if blank: # we want a blank library if library_file is none - super(ChannelLibrary, self).__init__(channelDict={}) - self.connectivityG = nx.DiGraph() +logger = logging.getLogger("QGL") + +def check_session_dirty(f): + """Since we can't mix db objects from separate sessions, re-fetch entities by their unique IDs""" + @wraps(f) + def wrapper(cls, *args, **kwargs): + if (len(cls.session.dirty | cls.session.new)) == 0: + if 'force' in kwargs: + kwargs.pop('force') + return f(cls, *args, **kwargs) + elif 'force' in kwargs and kwargs['force']: + kwargs.pop('force') + return f(cls, *args, **kwargs) else: - super(ChannelLibrary, self).__init__(channelDict=channelDict, library_file=self.library_file, **kwargs) - self.connectivityG = nx.DiGraph() - yaml_filenames = self.load_from_library() - if self.library_file and yaml_filenames: - self.fileWatcher = LibraryFileWatcher(self.library_file, self.update_from_file) + raise Exception("Uncommitted transactions for working database. Either use force=True or commit/revert your changes.") + return wrapper + +def check_for_duplicates(f): + """Since we can't mix db objects from separate sessions, re-fetch entities by their unique IDs""" + @wraps(f) + def wrapper(cls, label, *args, **kwargs): + if label in cls.channelDict: + logger.warning(f"A database item with the name {label} already exists. Updating parameters of this existing item instead.") + cls.channelDict[label].__dict__.update(kwargs) + return cls.channelDict[label] #should check for difference in args + else: + return f(cls, label, *args, **kwargs) + return wrapper + +class ChannelLibrary(object): + + def __init__(self, db_resource_name=":memory:", db_provider="sqlite"): + """Create the channel library.""" - # Update the global reference global channelLib - if channelLib: - # Don't let the - channelLib.fileWatcher = None + + bbndb.initialize_db(f'{db_provider}:///{db_resource_name}') + self.session = bbndb.get_cl_session() + self.connectivityG = nx.DiGraph() + self.db_provider = db_provider + self.db_resource_name = db_resource_name + + # Check to see whether there is already a temp database + working_dbs = self.query(Channels.ChannelDatabase, label="working").all() + if len(working_dbs) > 1: + raise Exception("More than one working database exists!") + elif len(working_dbs) == 1: + self.channelDatabase = working_dbs[0] + elif len(working_dbs) == 0: + self.channelDatabase = Channels.ChannelDatabase(label="working", time=datetime.datetime.now()) + self.add_and_update_dict(self.channelDatabase) + self.session.commit() + + self.update_channelDict() + + # Update the global reference + channelLib = self + + def query(self, obj_type, **kwargs): + return self.session.query(obj_type).filter_by(**kwargs) + + def get_current_channels(self): + return (self.channelDatabase.channels + + self.channelDatabase.generators + + self.channelDatabase.transmitters + + self.channelDatabase.receivers + + self.channelDatabase.transceivers + + self.channelDatabase.instruments + + self.channelDatabase.processors + + self.channelDatabase.attenuators + + self.channelDatabase.DCSources + + self.channelDatabase.spectrum_analyzers) + + def update_channelDict(self): + self.channelDict = {c.label: c for c in self.get_current_channels()} + self.build_connectivity_graph() + + def ls(self): + cdb = Channels.ChannelDatabase + q = self.session.query(cdb.label, cdb.time, cdb.id).\ + order_by(Channels.ChannelDatabase.id, Channels.ChannelDatabase.label).all() + table_code = "" + for i, (label, time, id) in enumerate(q): + y, d, t = map(time.strftime, ["%Y", "%b. %d", "%I:%M:%S %p"]) + # t = time.strftime("(%Y) %b. %d @ %I:%M:%S %p") + table_code += f"{id}{y}{d}{t}{label}" + display(HTML(f"{table_code}
idYearDateTimeName
")) + + def ent_by_type(self, obj_type, show=False): + q = self.session.query(obj_type).filter(obj_type.channel_db.has(label="working")).order_by(obj_type.label).all() + if show: + for i, el in enumerate(q): + print(f"[{i}] -> {el.label}") + else: + return q + + def show(self, qubits=[]): + # nodes = list(dgraph.nodes()) + edges = [] + qub_objs = qubits if not qubits == [] else self.qubits() + for q in qub_objs: + edges.append((q, q.measure_chan)) + edges.append((q.measure_chan, q.measure_chan.phys_chan)) + edges.append((q.measure_chan.phys_chan,q.measure_chan.phys_chan.transmitter)) + edges.append((q, q.phys_chan)) + edges.append((q.phys_chan, q.phys_chan.transmitter)) + + #Generators + if q.measure_chan.phys_chan.generator: + edges.append((q.measure_chan.phys_chan, q.measure_chan.phys_chan.generator)) + if q.phys_chan.generator: + edges.append((q.phys_chan, q.phys_chan.generator)) + + # Triggers + if q.measure_chan.trig_chan: + edges.append((q.measure_chan, q.measure_chan.trig_chan)) + + + graph = nx.digraph.DiGraph() + graph.add_edges_from(edges) + + indices = {n: i for i, n in enumerate(graph.nodes())} + node_data = [{'label': str(n).replace('(','\r\n(')} for n in graph.nodes()] + link_data = [{'source': indices[s], 'target': indices[t]} for s, t in graph.edges()] + + qub_objs.sort(key=lambda x: x.label) + qubit_names = [q.label for q in qub_objs] + + loc = {} + def next_level(nodes, iteration=0, offset=0, accum=[]): + if len(accum) == 0: + loc[nodes[0]] = {'x': 0, 'y': 0} + accum = [nodes] + next_gen_nodes = list(reduce(operator.add, [list(graph.successors(n)) for n in nodes])) + l = len(next_gen_nodes) + if l > 0: + for k,n in enumerate(next_gen_nodes): + loc[n] = {'x': k, 'y': -(iteration+1)} + accum.append(next_gen_nodes) + return next_level(next_gen_nodes, iteration=iteration+1, offset=2.5*l, accum=accum) + else: + return accum + + hierarchy = [next_level([q]) for q in qub_objs] + widest = [max([len(row) for row in qh]) for qh in hierarchy] + for i in range(1, len(qub_objs)): + offset = sum(widest[:i]) + loc[qub_objs[i]]['x'] += offset*3 + for n in nx.descendants(graph, qub_objs[i]): + loc[n]['x'] += offset*3 + + x = [loc[n]['x'] for n in graph.nodes()] + y = [loc[n]['y'] for n in graph.nodes()] + xs = LinearScale(min=min(x)-0.5, max=max(x)+0.6) + ys = LinearScale(min=min(y)-0.5, max=max(y)+0.6) + fig_layout = Layout(width='960px', height='500px') + bq_graph = Graph(node_data=node_data, link_data=link_data, x=x, y=y, scales={'x': xs, 'y': ys}, + link_type='line', colors=['orange'] * len(node_data), directed=False) + bgs_lines = [] + middles = [] + for i in range(len(qub_objs)): + if i==0: + start = -0.4 + end = widest[0]-0.6 + elif i == len(qub_objs): + start = sum(widest)-0.4 + end = max(x)+0.4 + else: + start = sum(widest[:i])-0.4 + end = sum(widest[:i+1])-0.6 + + fig = Figure(marks=[bq_graph], layout=fig_layout) + return fig + + def show_frequency_plan(self): + c_freqs = {} + m_freqs = {} + for qubit in self.qubits(): + c_freqs[qubit.label] = qubit.frequency*1e-9 + if qubit.phys_chan.generator: + c_freqs[qubit.label] += qubit.phys_chan.generator.frequency*1e-9 + + m_freqs[qubit.label] = qubit.measure_chan.frequency*1e-9 + if qubit.measure_chan.phys_chan.generator: + m_freqs[qubit.label] += qubit.measure_chan.phys_chan.generator.frequency*1e-9 + def spike_at(f): + fs = np.linspace(f-0.02,f+0.02,50) + return fs, np.exp(-(fs-f)**2/0.01**2) + figs = [] + for freqs, ss in zip([c_freqs, m_freqs],["Control","Measure"]): + sx = LinearScale() + sy = LinearScale() + ax = Axis(scale=sx, label="Frequency (GHz)") + ay = Axis(scale=sy, orientation='vertical') + lines = [] + for k,f in freqs.items(): + fs, a = spike_at(f) + lines.append(Lines(x=fs, y=a, scales={'x': sx, 'y': sy})) + labels = Label(x=list(freqs.values()), y=[1.1 for f in freqs], text=list(freqs.keys()), align='middle', scales= {'x': sx, 'y': sy}, + default_size=14, font_weight='bolder', colors=['#4f6367']) + figs.append(Figure(marks=lines+[labels], axes=[ax, ay], title=f"{ss} Frequency Plan")) + return HBox(figs) + + def receivers(self): + return self.ent_by_type(Channels.Receiver) + + def transmitters(self): + return self.ent_by_type(Channels.Transmitter) + + def transceivers(self): + return self.ent_by_type(Channels.Transceiver) + + def qubits(self): + return self.ent_by_type(Channels.Qubit) + + def meas(self): + return self.ent_by_type(Channels.Measurement) + + def markers(self): + return self.ent_by_type(Channels.LogicalMarkerChannel) + + @check_session_dirty + def load(self, name, index=1): + """Load the latest instance for a particular name. Specifying index = 2 will select the second most recent instance """ + cdb = Channels.ChannelDatabase + items = self.session.query(cdb).filter(cdb.label==name).order_by(cdb.time.desc()).all() + self.load_obj(items[-index]) + + @check_session_dirty + def load_by_id(self, id_num): + item = self.session.query(Channels.ChannelDatabase).filter_by(id=id_num).first() + self.load_obj(item) + + def clear(self, channel_db=None, create_new=True): + # If no database is specified, clear self.database + channel_db = channel_db if channel_db else self.channelDatabase + + self.session.delete(channel_db) + self.session.commit() + + if create_new: + self.channelDatabase = Channels.ChannelDatabase(label="working", time=datetime.datetime.now()) + self.add_and_update_dict(self.channelDatabase) + self.session.commit() channelLib = self - self.last_library_update = str(datetime.datetime.now()) + def rm(self, library_name, keep_id=-1): + """Remove the channel library named `library_name`. If no `keep_version` is specified then + all versions are removed. Otherwise """ + cdb = Channels.ChannelDatabase + items = self.session.query(cdb).filter(cdb.label==library_name and cdb.id!=keep_id).all() + for item in items: + self.session.delete(item) + + def rm_by_id(self, id): + """Remove the channel library with id `id`""" + item = self.session.query(Channels.ChannelDatabase).filter_by(id=id_num).first() + self.session.delete(item) + + def load_obj(self, obj): + self.clear(create_new=False) + self.channelDatabase = bbndb.deepcopy_sqla_object(obj, self.session) + self.channelDatabase.label = "working" + self.session.commit() + self.update_channelDict() + + def commit(self): + self.session.commit() + self.update_channelDict() + + def revert(self): + self.session.rollback() + + @check_session_dirty + def save_as(self, name): + if name == "working": + raise ValueError("Cannot save as `working` since that is the default working environment name...") + self.commit() + new_channelDatabase = bbndb.deepcopy_sqla_object(self.channelDatabase, self.session) + new_channelDatabase.label = name + new_channelDatabase.time = datetime.datetime.now() + self.commit() + + def add_and_update_dict(self, el): + if isinstance(el, list): + self.session.add_all(el) + else: + self.session.add(el) + self.update_channelDict() #Dictionary methods def __getitem__(self, key): @@ -179,395 +370,292 @@ def values(self): def build_connectivity_graph(self): # build connectivity graph - self.connectivityG.clear() - for chan in self.channelDict.values(): - if isinstance(chan, - Channels.Qubit) and chan not in self.connectivityG: - self.connectivityG.add_node(chan) - for chan in self.channelDict.values(): - if isinstance(chan, Channels.Edge): - self.connectivityG.add_edge(chan.source, chan.target) - self.connectivityG[chan.source][chan.target]['channel'] = chan - - def load_from_library(self, return_only=False): - """Loads the YAML library, creates the QGL objects, and returns a list of the visited filenames - for the filewatcher.""" - if not self.library_file: - return - try: - with open(self.library_file, 'r') as FID: - loader = config.Loader(FID) - try: - tmpLib = loader.get_single_data() - filenames = loader.filenames - finally: - loader.dispose() - - # Check to see if we have the mandatory sections - for section in ['instruments', 'qubits', 'filters']: - if section not in tmpLib.keys(): - raise ValueError("{} section not present in config file {}.".format(section, self.library_file)) - - instr_dict = tmpLib['instruments'] - qubit_dict = tmpLib['qubits'] - filter_dict = tmpLib['filters'] - trigger_dict = tmpLib.get('markers', {}) # This section is optional - edge_dict = tmpLib.get('edges', {}) # This section is optional - master_awgs = [] - - # Construct the channel library - channel_dict = {} - marker_lens = {} - - for name, instr in instr_dict.items(): - if "tx_channels" in instr.keys(): - for chan_name, channel in instr["tx_channels"].items(): - if channel is None: - params = {} - else: - params = {k: v for k,v in channel.items() if k in Channels.PhysicalQuadratureChannel.__atom_members__.keys()} - params["label"] = name + "-" + chan_name - params["instrument"] = name - params["translator"] = instr["type"] + "Pattern" - params["__module__"] = "QGL.Channels" - params["__class__"] = "PhysicalQuadratureChannel" - channel_dict[params["label"]] = params - if "rx_channels" in instr.keys(): - for chan_name, channel in instr["rx_channels"].items(): - if channel is None: - params = {} - else: - params = {k: v for k,v in channel.items() if k in Channels.PhysicalMarkerChannel.__atom_members__.keys()} - params["label"] = name + "-" + chan_name - params["instrument"] = name - params["translator"] = instr["type"] + "Pattern" - params["__module__"] = "QGL.Channels" - params["__class__"] = "PhysicalMarkerChannel" - channel_dict[params["label"]] = params - if "markers" in instr.keys(): - for mark_name, marker in instr["markers"].items(): - if marker is None: - params = {} - else: - params = {k: v for k,v in marker.items() if k in Channels.PhysicalMarkerChannel.__atom_members__.keys()} - params["label"] = name + "-" + mark_name - params["instrument"] = name - params["translator"] = instr["type"] + "Pattern" - params["__module__"] = "QGL.Channels" - params["__class__"] = "PhysicalMarkerChannel" - if "length" in marker.keys(): - marker_lens[params["label"]] = marker["length"] - channel_dict[params["label"]] = params - if "master" in instr.keys() and instr["master"]: - if instr['type'] != 'TDM': - slave_chan = instr["slave_trig"] if "slave_trig" in instr.keys() else "slave" - master_awgs.append(name + "-" + slave_chan) - else: - master_awgs.append(name) - # Eventually we should support multiple masters... - if "slave_trig" in instr.keys(): - params = {} - params["label"] = "slave_trig" - params["phys_chan"] = name + "-" + instr["slave_trig"] - if params["phys_chan"] in marker_lens.keys(): - length = marker_lens[params["phys_chan"]] - else: - length = 1e-7 - params["pulse_params"] = {"length": length, "shape_fun": "constant"} - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - channel_dict[params["label"]] = params - - # Establish the slave trigger, assuming for now that we have a single - # APS master. This might change later. - if len(master_awgs) > 1: - raise ValueError("More than one AWG is marked as master.") - # elif len(master_awgs) == 1 and instr_dict[master_awgs[0].split('-')[0]]['type'] != 'TDM': - # params = {} - # params["label"] = "slave_trig" - # params["phys_chan"] = master_awgs[0] - # if params["phys_chan"] in marker_lens.keys(): - # length = marker_lens[params["phys_chan"]] - # else: - # length = 1e-7 - # params["pulse_params"] = {"length": length, "shape_fun": "constant"} - # params["__module__"] = "QGL.Channels" - # params["__class__"] = "LogicalMarkerChannel" - # channel_dict[params["label"]] = params - - for name, filt in filter_dict.items(): - if "StreamSelector" in filt["type"]: - params = {k: v for k,v in filt.items() if k in Channels.ReceiverChannel.__atom_members__.keys()} - params["label"] = "RecvChan-" + name # instr_dict[filt["instrument"]]["name"] + "-" + name - params["channel"] = str(params["channel"]) # Convert to a string - params["instrument"] = filt["source"] - params["__module__"] = "QGL.Channels" - params["__class__"] = "ReceiverChannel" - if "source" not in filt.keys(): - raise ValueError("No instrument (source) specified for Stream Selector") - if filt["source"] not in instr_dict.keys() and filt["source"] not in channel_dict.keys(): - raise ValueError("Stream Selector source {} not found among list of instruments.".format(filt["source"])) - params["instrument"] = filt["source"] - - channel_dict[params["label"]] = params - - for name, qubit in qubit_dict.items(): - # Create the Qubits - if len(qubit["control"]["AWG"].split()) != 2: - print("Control AWG specification for {} ({}) must have a device, channel".format(name, qubit["control"]["AWG"])) - raise ValueError("Control AWG specification for {} ({}) must have a device, channel".format(name, qubit["control"]["AWG"])) - ctrl_instr, ctrl_chan = qubit["control"]["AWG"].split() - params = {k: v for k,v in qubit["control"].items() if k in Channels.Qubit.__atom_members__.keys()} - params["label"] = name - params["phys_chan"] = ctrl_instr + "-" + ctrl_chan - params["__module__"] = "QGL.Channels" - params["__class__"] = "Qubit" - channel_dict[params["label"]] = params - if 'generator' in qubit["control"].keys(): - channel_dict[params["phys_chan"]]["generator"] = qubit["control"]["generator"] - - # Create the measurements - if len(qubit["measure"]["AWG"].split()) != 2: - print("Measurement AWG specification for {} ({}) must have a device, channel".format(name, qubit["measure"]["AWG"])) - raise ValueError("Measurement AWG specification for {} ({}) must have a device, channel".format(name, qubit["measure"]["AWG"])) - meas_instr, meas_chan = qubit["measure"]["AWG"].split() - params = {k: v for k,v in qubit["measure"].items() if k in Channels.Measurement.__atom_members__.keys()} - params["label"] = "M-{}".format(name) - # parse the digitizer trigger from the marker dictionary, if available. If not, expected in the form Instr Ch - dig_trig = trigger_dict.get(qubit["measure"]["trigger"], qubit["measure"]["trigger"]) if trigger_dict else qubit["measure"]["trigger"] - params["trig_chan"] = "digTrig-" + dig_trig - params["phys_chan"] = meas_instr + "-" + meas_chan - params["meas_type"] = "autodyne" - params["receiver_chan"] = "RecvChan-" + qubit["measure"]["receiver"] - params["__module__"] = "QGL.Channels" - params["__class__"] = "Measurement" - channel_dict[params["label"]] = params - if 'generator' in qubit["measure"].keys(): - channel_dict[params["phys_chan"]]["generator"] = qubit["measure"]["generator"] - - # Create the receiver channels - if "receiver" in qubit["measure"].keys(): - if len(qubit["measure"]["receiver"].split()) != 1: - print("Receiver specification for {} ({}) must have a stream selector".format(name, qubit["measure"]["receiver"])) - raise ValueError("Receiver specification for {} ({}) must have a stream selector".format(name, qubit["measure"]["receiver"])) - phys_instr, phys_marker = dig_trig.split() - params = {} - params["label"] = "digTrig-" + dig_trig - params["phys_chan"] = phys_instr + "-" + phys_marker - if params["phys_chan"] in marker_lens.keys(): - length = marker_lens[params["phys_chan"]] - else: - length = 3e-7 - params["pulse_params"] = {"length": length, "shape_fun": "constant"} - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - # Don't duplicate triggers to the same digitizer - if params["label"] not in channel_dict.keys(): - channel_dict[params["label"]] = params - - # Create the measurement gate chan: - if "gate" in qubit["measure"].keys(): - phys_instr, phys_marker = qubit["measure"]["gate"].split() - params = {} - params["label"] = "M-{}-gate".format(name) - params["phys_chan"] = phys_instr + "-" + phys_marker - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - channel_dict[params["label"]] = params - channel_dict["M-{}".format(name)]["gate_chan"] = params["label"] - - # Create the control gate chan: - if "gate" in qubit["control"].keys(): - phys_instr, phys_marker = qubit["control"]["gate"].split() - params = {} - params["label"] = "{}-gate".format(name) - params["phys_chan"] = phys_instr + "-" + phys_marker - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - channel_dict[params["label"]] = params - channel_dict[name]["gate_chan"] = params["label"] - - - for trig_name, trigger in trigger_dict.items(): - phys_instr, phys_marker = trigger.split() - params = {} - params["label"] = trig_name - params["phys_chan"] = phys_instr + "-" + phys_marker - if params["phys_chan"] in marker_lens.keys(): - length = marker_lens[params["phys_chan"]] - else: - length = 1e-7 - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - channel_dict[params["label"]] = params - - for name, edge in edge_dict.items(): - # Create the Edges - if len(edge["AWG"].split()) != 2: - print("Control AWG specification for {} ({}) must have a device, channel".format(name, edge["AWG"])) - raise ValueError("Control AWG specification for {} ({}) must have a device, channel".format(name, edge["AWG"])) - ctrl_instr, ctrl_chan = edge["AWG"].split() - params = {k: v for k,v in edge.items() if k in Channels.Edge.__atom_members__.keys()} - params["label"] = name - params["phys_chan"] = ctrl_instr + "-" + ctrl_chan - params["__module__"] = "QGL.Channels" - params["__class__"] = "Edge" - channel_dict[params["label"]] = params - if 'generator' in edge.keys(): - channel_dict[params["phys_chan"]]["generator"] = edge["generator"] - - # Create the edge gate chan: - if "gate" in edge.keys(): - phys_instr, phys_marker = edge["gate"].split() - params = {} - params["label"] = "{}-gate".format(name) - params["phys_chan"] = phys_instr + "-" + phys_marker - params["__module__"] = "QGL.Channels" - params["__class__"] = "LogicalMarkerChannel" - channel_dict[params["label"]] = params - channel_dict[name]["gate_chan"] = params["label"] - - if return_only: - return channel_dict - else: - channel_dict = {k: self.instantiate(v) for k,v in channel_dict.items()} - # connect objects labeled by strings - for chan in channel_dict.values(): - for param in self.specialParams: - if hasattr(chan, param) and getattr(chan, param) is not None: - chan_to_find = channel_dict.get(getattr(chan, param), None) - if not chan_to_find: - print("Couldn't find {} of {} in the channel_dict!".format(param, chan)) - setattr(chan, param, chan_to_find) - - self.channelDict.update(channel_dict) - self.build_connectivity_graph() - return filenames - - except IOError: - print('No channel library found.') - except Exception as e: - print('Failed to load channel library: received exception', e) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback, limit=4, file=sys.stdout) - - def instantiate(self, paramDict): - if 'pulse_params' in paramDict: - if 'shape_fun' in paramDict['pulse_params']: - shape_fun = paramDict['pulse_params']['shape_fun'] - paramDict['pulse_params']['shape_fun'] = getattr(PulseShapes, shape_fun) - if '__class__' in paramDict: - className = paramDict.pop('__class__') - moduleName = paramDict.pop('__module__') - __import__(moduleName) - return getattr(sys.modules[moduleName], className)(**paramDict) - - - def update_from_file(self): + for chan in self.session.query(Channels.Qubit).filter(Channels.Qubit not in self.connectivityG).all(): + self.connectivityG.add_node(chan) + for chan in self.session.query(Channels.Edge): #select(e for e in Channels.Edge): + self.connectivityG.add_edge(chan.source, chan.target) + self.connectivityG[chan.source][chan.target]['channel'] = chan + + @check_for_duplicates + def new_APS2(self, label, address, **kwargs): + chan1 = Channels.PhysicalQuadratureChannel(label=f"{label}-1", channel=0, instrument=label, translator="APS2Pattern", channel_db=self.channelDatabase) + m1 = Channels.PhysicalMarkerChannel(label=f"{label}-m1", channel=0, instrument=label, translator="APS2Pattern", channel_db=self.channelDatabase) + m2 = Channels.PhysicalMarkerChannel(label=f"{label}-m2", channel=1, instrument=label, translator="APS2Pattern", channel_db=self.channelDatabase) + m3 = Channels.PhysicalMarkerChannel(label=f"{label}-m3", channel=2, instrument=label, translator="APS2Pattern", channel_db=self.channelDatabase) + m4 = Channels.PhysicalMarkerChannel(label=f"{label}-m4", channel=3, instrument=label, translator="APS2Pattern", channel_db=self.channelDatabase) + + this_transmitter = Channels.Transmitter(label=label, model="APS2", address=address, channels=[chan1, m1, m2, m3, m4], channel_db=self.channelDatabase, **kwargs) + this_transmitter.trigger_source = "external" + this_transmitter.address = address + + self.add_and_update_dict(this_transmitter) + return this_transmitter + + @check_for_duplicates + def new_APS(self, label, address, **kwargs): + chan1 = Channels.PhysicalQuadratureChannel(label=f"{label}-12", channel = 0, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + chan2 = Channels.PhysicalQuadratureChannel(label=f"{label}-34", channel = 1, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + m1 = Channels.PhysicalMarkerChannel(label=f"{label}-1m1", channel=0, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + m2 = Channels.PhysicalMarkerChannel(label=f"{label}-2m1", channel=1, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + m3 = Channels.PhysicalMarkerChannel(label=f"{label}-3m1", channel=2, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + m4 = Channels.PhysicalMarkerChannel(label=f"{label}-4m1", channel=3, instrument=label, translator="APSPattern", channel_db=self.channelDatabase) + + this_transmitter = Channels.Transmitter(label=label, model="APS", address=address, channels=[chan1, chan2, m1, m2, m3, m4], channel_db=self.channelDatabase) + this_transmitter.trigger_source = "external" + this_transmitter.address = address + + self.add_and_update_dict(this_transmitter) + return this_transmitter + + @check_for_duplicates + def new_TDM(self, label, address, **kwargs): + return Channels.Processor(label=label, model="TDM", address=address, trigger_interval=250e-6) + + @check_for_duplicates + def new_spectrum_analzyer(self, label, address, source, **kwargs): + sa = Channels.SpectrumAnalyzer(label=label, model="SpectrumAnalyzer", address=address, LO_source=source, channel_db=self.channelDatabase, **kwargs) + self.add_and_update_dict(sa) + return sa + + @check_for_duplicates + def new_DC_source(self, label, address, **kwargs): + dcsource = Channels.DCSource(label=label, model="YokogawaGS200", address=address, standalone=True, channel_db=self.channelDatabase, **kwargs) + self.add_and_update_dict(dcsource) + return dcsource + + @check_for_duplicates + def new_attenuator(self,label,address,attenuation=0): + chan1 = Channels.AttenuatorChannel(label=f"AttenChan-{label}-1", channel=1, attenuation=attenuation, channel_db=self.channelDatabase) + chan2 = Channels.AttenuatorChannel(label=f"AttenChan-{label}-2", channel=2, attenuation=attenuation, channel_db=self.channelDatabase) + chan3 = Channels.AttenuatorChannel(label=f"AttenChan-{label}-3", channel=3, attenuation=attenuation, channel_db=self.channelDatabase) + thing = Channels.Attenuator(label=label,model="DigitalAttenuator",address=address,channels=[chan1, chan2, chan3], standalone=True, channel_db=self.channelDatabase) + self.add_and_update_dict(thing) + return thing + + @check_for_duplicates + def new_APS2_rack(self, label, ip_addresses, tdm_ip=None, **kwargs): + transmitters = [self.new_APS2(f"{label}_U{n+1}", f"{ip}") for n, ip in enumerate(ip_addresses)] + this_transceiver = Channels.Transceiver(label=label, model="APS2", master=True, address=ip_addresses[0], transmitters=transmitters, channel_db=self.channelDatabase, **kwargs) + for t in transmitters: + t.transceiver = this_transceiver + + if tdm_ip: + tdm = self.new_TDM(f"{label}_TDM", tdm_ip) + this_transceiver.processors = [tdm] + for t in transmitters: + t.trigger_source = 'system' + + self.add_and_update_dict(this_transceiver) + return this_transceiver + + @check_for_duplicates + def new_X6(self, label, address, dsp_channel=0, record_length=1024, **kwargs): + + phys_channels = (1, 2) + chans = [] + + for phys_chan in (1,2): + chans.append(Channels.ReceiverChannel(label=f"RecvChan-{label}-{phys_chan}", + channel=phys_chan, channel_db=self.channelDatabase)) + + this_receiver = Channels.Receiver(label=label, model="X6", address=address, channels=chans, + record_length=record_length, channel_db=self.channelDatabase, **kwargs) + this_receiver.trigger_source = "external" + this_receiver.stream_types = "raw, demodulated, integrated" + this_receiver.address = address + this_receiver.stream_sel = "X6StreamSelector" + + self.add_and_update_dict(this_receiver) + return this_receiver + + @check_for_duplicates + def new_Alazar(self, label, address, record_length=1024, **kwargs): + chan1 = Channels.ReceiverChannel(label=f"RecvChan-{label}-1", channel=1, channel_db=self.channelDatabase) + chan2 = Channels.ReceiverChannel(label=f"RecvChan-{label}-2", channel=2, channel_db=self.channelDatabase) + + this_receiver = Channels.Receiver(label=label, model="AlazarATS9870", address=address, channels=[chan1, chan2], + record_length=record_length, channel_db=self.channelDatabase, **kwargs) + this_receiver.trigger_source = "external" + this_receiver.stream_types = "raw" + this_receiver.address = address + this_receiver.stream_sel = "AlazarStreamSelector" + + self.add_and_update_dict(this_receiver) + return this_receiver + + @check_for_duplicates + def new_qubit(self, label, **kwargs): + thing = Channels.Qubit(label=label, channel_db=self.channelDatabase, **kwargs) + self.add_and_update_dict(thing) + return thing + + @check_for_duplicates + def new_marker(self, label, phys_chan, **kwargs): + thing = Channels.LogicalMarkerChannel(label=label, phys_chan = phys_chan, channel_db=self.channelDatabase, **kwargs) + self.add_and_update_dict(thing) + return thing + + @check_for_duplicates + def new_source(self, label, model, address, power=-30.0, frequency=5.0e9, reference='10MHz', **kwargs): + thing = Channels.Generator(label=label, model=model, address=address, power=power, + frequency=frequency, reference=reference, + channel_db=self.channelDatabase, **kwargs) + self.add_and_update_dict(thing) + return thing + + def set_control(self, qubit_or_edge, transmitter, generator=None): + + if isinstance(transmitter, Channels.Transmitter): + quads = [c for c in transmitter.channels if isinstance(c, Channels.PhysicalQuadratureChannel)] + markers = [c for c in transmitter.channels if isinstance(c, Channels.PhysicalMarkerChannel)] + if len(quads) > 1: + raise ValueError("In set_control the Transmitter must have a single quadrature channel or a specific channel must be passed instead") + elif len(quads) == 1: + phys_chan = quads[0] + elif isinstance(transmitter, Channels.PhysicalQuadratureChannel): + phys_chan = transmitter + markers = [c for c in transmitter.transmitter.channels if isinstance(c, Channels.PhysicalMarkerChannel)] + else: + raise ValueError("In set_control the Transmitter must have a single quadrature channel or a specific channel must be passed instead") + + qubit_or_edge.phys_chan = phys_chan + if generator: + qubit_or_edge.phys_chan.generator = generator + self.update_channelDict() + + def new_edge(self, source, target): + label = f"{source.label}->{target.label}" + if label in self.channelDict: + edge = self.channelDict[f"{source.label}->{target.label}"] + logger.warning(f"The edge {source.label}->{target.label} already exists: using this edge.") + else: + edge = Channels.Edge(label=f"{source.label}->{target.label}", source=source, target=target, channel_db=self.channelDatabase) + self.add_and_update_dict(edge) + return edge + + def set_qubit_connectivity(self, graph): """ - Only update relevant parameters - Helps avoid both stale references from replacing whole channel objects (as in load_from_library) - and the overhead of recreating everything. + Graph is a networkx DiGraph consisting of edges (source qubit, target qubit) """ + new_edges = [Channels.Edge(label=f"{source.label}->{target.label}", source=source, target=target) for source, target in graph.edges()] + self.add_and_update_dict(new_edges) + return new_edges + + def set_measure(self, qubit, transmitter, receivers, generator=None, trig_channel=None, gate=False, gate_channel=None, trigger_length=1e-7): + + if isinstance(transmitter, Channels.Transmitter): + quads = [c for c in transmitter.channels if isinstance(c, Channels.PhysicalQuadratureChannel)] + markers = [c for c in transmitter.channels if isinstance(c, Channels.PhysicalMarkerChannel)] + if len(quads) > 1: + raise ValueError("In set_measure the Transmitter must have a single quadrature channel or a specific channel must be passed instead") + elif len(quads) == 1: + phys_chan = quads[0] + elif isinstance(transmitter, Channels.PhysicalQuadratureChannel): + phys_chan = transmitter + markers = [c for c in transmitter.transmitter.channels if isinstance(c, Channels.PhysicalMarkerChannel)] + else: + raise ValueError("In set_measure the Transmitter must have a single quadrature channel or a specific channel must be passed instead") - if not self.library_file: - return - try: - all_params = self.load_from_library(return_only=True) - - # update & insert - for chName, chParams in all_params.items(): - if chName in self.channelDict: - self.update_from_json(chName, chParams) - else: - self.channelDict[chName] = self.instantiate(chParams) - self.update_from_json(chName, chParams) - - # remove - for chName in list(self.channelDict.keys()): - if chName not in all_params: - del self.channelDict[chName] - - self.build_connectivity_graph() - - print("Updated library") - self.last_library_update = str(datetime.datetime.now()) - except: - print('Failed to update channel library from file. Is there a typo?.') - return - - # reset pulse cache - from . import PulsePrimitives - PulsePrimitives._memoize.cache.clear() - - - def update_from_json(self, chName, chParams): - # connect objects labeled by strings - if 'pulse_params' in chParams.keys(): - paramDict = {str(k): v for k, v in chParams['pulse_params'].items()} - shapeFunName = paramDict.pop('shape_fun', None) - if shapeFunName: - paramDict['shape_fun'] = getattr(PulseShapes, shapeFunName) - self.channelDict[chName].pulse_params = paramDict - - for param in self.specialParams: - if param in chParams.keys(): - setattr(self.channelDict[chName], - param, - self.channelDict.get(chParams[param], None) - ) - # TODO: how do we follow changes to selected AWG or generator? - - # ignored or specially handled parameters - ignoreList = self.specialParams + ['pulse_params', 'AWG', 'generator', '__class__', '__module__'] - for paramName in chParams: - if paramName not in ignoreList: - setattr(self.channelDict[chName], paramName, chParams[paramName]) - - def on_awg_change(self, oldName, newName): - print("Change AWG", oldName, newName) - for chName in self.channelDict: - if isinstance(self.channelDict[chName], - (Channels.PhysicalMarkerChannel, - Channels.PhysicalQuadratureChannel)): - awgName, awgChannel = chName.rsplit('-', 1) - if awgName == oldName: - newLabel = "{0}-{1}".format(newName, awgChannel) - print("Changing {0} to {1}".format(chName, newLabel)) - self.physicalChannelManager.name_changed(chName, newLabel) - -def MarkerFactory(label, **kwargs): - '''Return a marker channel by name. Must be defined under top-level `markers` - keyword in measurement configuration YAML. - ''' - if not channelLib: - raise ValueError('ChannelLibrary not found, has an instance of ChannelLibrary been created?') - if label in channelLib and isinstance(channelLib[label], Channels.LogicalMarkerChannel): - return channelLib[label] - else: - raise ValueError("Marker channel {} not found in channel library.".format(label)) - -def QubitFactory(label, **kwargs): - ''' Return a saved qubit channel or create a new one. ''' - if not channelLib: - raise ValueError('ChannelLibrary not found, has an instance of ChannelLibrary been created?') - if label in channelLib and isinstance(channelLib[label], Channels.Qubit): - return channelLib[label] + if f"M-{qubit.label}" in self.channelDict: + logger.warning(f"The measurement M-{qubit.label} already exists: using this measurement.") + meas = self.channelDict[f"M-{qubit.label}"] + else: + meas = Channels.Measurement(label=f"M-{qubit.label}", channel_db=self.channelDatabase) + meas.phys_chan = phys_chan + if generator: + meas.phys_chan.generator = generator + + phys_trig_channel = trig_channel if trig_channel else transmitter.get_chan("m1") + + if f"ReceiverTrig-{qubit.label}" in self.channelDict: + logger.warning(f"The Receiver trigger ReceiverTrig-{qubit.label} already exists: using this channel.") + trig_chan = self.channelDict[f"ReceiverTrig-{qubit.label}"] + else: + trig_chan = Channels.LogicalMarkerChannel(label=f"ReceiverTrig-{qubit.label}", channel_db=self.channelDatabase) + self.session.add(trig_chan) + trig_chan.phys_chan = phys_trig_channel + trig_chan.pulse_params = {"length": trigger_length, "shape_fun": "constant"} + meas.trig_chan = trig_chan + qubit.measure_chan = meas + + if isinstance(receivers, Channels.Receiver) and len(receivers.channels) > 1: + raise ValueError("In set_measure the Receiver must have a single receiver channel or a specific channel must be passed instead") + elif isinstance(receivers, Channels.Receiver) and len(receivers.channels) == 1: + rcv_chan = receivers.channels[0] + elif isinstance(receivers, Channels.ReceiverChannel): + rcv_chan = receivers + else: + raise ValueError("In set_measure the Transmitter must have a single quadrature channel or a specific channel must be passed instead") + + meas.receiver_chan = rcv_chan + self.add_and_update_dict([meas, trig_chan]) + + if gate: + phys_gate_channel = gate_channel if gate_channel else transmitter.get_chan("m2") + if f"M-{qubit.label}-gate" in self.channelDict: + logger.warning(f"The gate channel M-{qubit.label}-gate already exists: using this channel.") + gate_chan = self.channelDict[f"M-{qubit.label}-gate"] + gate_chan = Channels.LogicalMarkerChannel(label=f"M-{qubit.label}-gate", channel_db=self.channelDatabase) + gate_chan.phys_chan = phys_gate_channel + meas.gate_chan = gate_chan + self.add_and_update_dict([gate_chan]) + + def set_master(self, master_instrument, trig_channel=None, pulse_length=1e-7): + + if isinstance(master_instrument, Channels.Processor): + master_instrument.master = True + + elif trig_channel: + + if not isinstance(trig_channel, Channels.PhysicalMarkerChannel): + raise ValueError("In set_master the trigger channel must be an instance of PhysicalMarkerChannel") + + if "slave_trig" in self.channelDict: + logger.warning(f"The slave trigger slave_trig already exists: using this trigger.") + st = self.channelDict["slave_trig"] + else: + st = Channels.LogicalMarkerChannel(label="slave_trig", channel_db=self.channelDatabase) + st.phys_chan = trig_channel + st.pulse_params = {"length": pulse_length, "shape_fun": "constant"} + master_instrument.master = True + master_instrument.trigger_source = "internal" + self.add_and_update_dict([st]) + + else: + raise ValueError(f"Could not determine which transmitter to set as master for {transmitter}:{trig_channel}") + +def QubitFactory(label): + ''' Return a saved qubit channel''' + channelLib.update_channelDict() + cs = [c for c in channelLib.channelDatabase.channels if c.label==label] + # q = channelLib.session.query(Channels.Qubit).filter(Channels.Qubit.label==label and Channels.Qubit.channel_db==channelLib.channelDatabase).all() + if len(cs) == 1: + return cs[0] else: - return Channels.Qubit(label=label, **kwargs) + raise Exception(f"Expected to find a single qubit {label} but found {len(cs)} qubits with the same label instead.") -def MeasFactory(label, meas_type='autodyne', **kwargs): +def MeasFactory(label): ''' Return a saved measurement channel or create a new one. ''' - if not channelLib: - raise ValueError('ChannelLibrary not found, has an instance of ChannelLibrary been created?') - if label in channelLib and isinstance(channelLib[label], Channels.Measurement): - return channelLib[label] + channelLib.update_channelDict() + cs = [c for c in channelLib.channelDatabase.channels if c.label==label] + # q = channelLib.session.query(Channels.Qubit).filter(Channels.Qubit.label==label and Channels.Qubit.channel_db==channelLib.channelDatabase).all() + if len(cs) == 1: + return cs[0] + else: + raise Exception(f"Expected to find a single measurement {label} but found {len(cs)} measurements with the same label instead.") + +def MarkerFactory(label): + ''' Return a saved Marker channel or create a new one. ''' + cs = [c for c in channelLib.channelDatabase.channels if c.label==label] + channelLib.update_channelDict() + # q = channelLib.session.query(Channels.Qubit).filter(Channels.Qubit.label==label and Channels.Qubit.channel_db==channelLib.channelDatabase).all() + if len(cs) == 1: + return cs[0] else: - return Channels.Measurement(label=label, meas_type=meas_type, **kwargs) + raise Exception(f"Expected to find a single marker {label} but found {len(cs)} markers with the same label instead.") def EdgeFactory(source, target): - if not channelLib: - raise ValueError('Connectivity graph not found. Has a ChannelLibrary has been created?') + channelLib.update_channelDict() if channelLib.connectivityG.has_edge(source, target): return channelLib.connectivityG[source][target]['channel'] elif channelLib.connectivityG.has_edge(target, source): diff --git a/QGL/Channels.py b/QGL/Channels.py index c0c85163..1c9807d4 100644 --- a/QGL/Channels.py +++ b/QGL/Channels.py @@ -4,6 +4,7 @@ Created on Jan 19, 2012 Original Author: Colm Ryan +Modified By: Graham Rowlands Copyright 2013 Raytheon BBN Technologies @@ -20,204 +21,6 @@ limitations under the License. ''' +from . import config from . import PulseShapes -import numpy as np - -from math import tan, cos, pi -# Python 2/3 compatibility: use the py3 meaning of 'str' -from builtins import str - -from atom.api import Atom, Str, Float, Instance, \ - Dict, Enum, Bool, Typed, Int - -from copy import deepcopy - - -class Channel(Atom): - ''' - Every channel has a label and some printers. - ''' - label = Str() - enabled = Bool(True) - - def __repr__(self): - return str(self) - - def __str__(self): - return "{0}('{1}')".format(self.__class__.__name__, self.label) - - def json_encode(self): - jsonDict = self.__getstate__() - - #Turn objects into labels - for member in ["phys_chan", "gate_chan", "trig_chan", "receiver_chan", "source", "target"]: - if member in jsonDict and not isinstance(jsonDict[member], str): - obj = jsonDict.pop(member) - if obj: - jsonDict[member] = obj.label - - #We want the name of shape functions - if "pulse_params" in jsonDict: - pulse_params = deepcopy(jsonDict.pop("pulse_params")) - if "shape_fun" in pulse_params: - pulse_params["shape_fun"] = pulse_params["shape_fun"].__name__ - jsonDict["pulse_params"] = pulse_params - - return jsonDict - - -class PhysicalChannel(Channel): - ''' - The main class for actual AWG channels. - ''' - instrument = Str() # i.e. the AWG or receiver - translator = Str() - generator = Str() - sampling_rate = Float(default=1.2e9) - delay = Float() - - -class LogicalChannel(Channel): - ''' - The main class from which we will generate sequences. - At some point it needs to be assigned to a physical channel. - ''' - #During initilization we may just have a string reference to the channel - phys_chan = Instance((str, PhysicalChannel)) - - def __init__(self, **kwargs): - super(LogicalChannel, self).__init__(**kwargs) - if self.phys_chan is None: - self.phys_chan = PhysicalChannel(label=kwargs['label'] + '-phys') - - -class PhysicalMarkerChannel(PhysicalChannel): - ''' - A digital output channel on an AWG. - ''' - gate_buffer = Float(0.0).tag( - desc="How much extra time should be added onto the beginning of a gating pulse") - gate_min_width = Float(0.0).tag(desc="The minimum marker pulse width") - - -class PhysicalQuadratureChannel(PhysicalChannel): - ''' - Something used to implement a standard qubit channel with two analog channels and a microwave gating channel. - ''' - I_channel = Str() - Q_channel = Str() - #During initilization we may just have a string reference to the channel - amp_factor = Float(1.0) - phase_skew = Float(0.0) - - @property - def correctionT(self): - return np.array( - [[self.amp_factor, self.amp_factor * tan(self.phase_skew * pi / 180)], - [0, 1 / cos(self.phase_skew * pi / 180)]]) - -class ReceiverChannel(PhysicalChannel): - ''' - A trigger input on a receiver. - ''' - channel = Str() - -class LogicalMarkerChannel(LogicalChannel): - ''' - A class for digital channels for gating sources or triggering other things. - ''' - pulse_params = Dict(default={'shape_fun': PulseShapes.constant, - 'length': 10e-9}) - - -class Qubit(LogicalChannel): - ''' - The main class for generating qubit pulses. Effectively a logical "QuadratureChannel". - ''' - pulse_params = Dict(default={'length': 20e-9, - 'piAmp': 1.0, - 'pi2Amp': 0.5, - 'shape_fun': PulseShapes.gaussian, - 'cutoff': 2, - 'drag_scaling': 0, - 'sigma': 5e-9}) - gate_chan = Instance((str, LogicalMarkerChannel)) - frequency = Float(0.0).tag( - desc='modulation frequency of the channel (can be positive or negative)') - - def __init__(self, **kwargs): - super(Qubit, self).__init__(**kwargs) - - -class Measurement(LogicalChannel): - ''' - A class for measurement channels. - Measurements are special because they can be different types: - autodyne which needs an IQ pair or hetero/homodyne which needs just a marker channel. - ''' - meas_type = Enum('autodyne', 'homodyne').tag( - desc='Type of measurement (autodyne, homodyne)') - - autodyne_freq = Float(0.0).tag( - desc='use to bake the modulation into the pulse, so that it has constant phase') - frequency = Float(0.0).tag( - desc='use frequency to asssociate modulation with the channel') - pulse_params = Dict(default={'length': 100e-9, - 'amp': 1.0, - 'shape_fun': PulseShapes.tanh, - 'cutoff': 2, - 'sigma': 1e-9}) - gate_chan = Instance((str, LogicalMarkerChannel)) - trig_chan = Instance((str, LogicalMarkerChannel)) - receiver_chan = Instance((str, ReceiverChannel)) - - def __init__(self, **kwargs): - super(Measurement, self).__init__(**kwargs) - if self.trig_chan is None: - self.trig_chan = LogicalMarkerChannel(label='digitizerTrig') - - -class Edge(LogicalChannel): - ''' - Defines an arc/directed edge between qubit vertices. If a device supports bi-directional - connectivity, that is represented with two independent Edges. - - An Edge is also effectively an abstract channel, so it carries the same properties as a - Qubit channel. - ''' - # allow string in source and target so that we can store a label or an object - source = Instance((str, Qubit)) - target = Instance((str, Qubit)) - pulse_params = Dict(default={'length': 20e-9, - 'amp': 1.0, - 'phase': 0.0, - 'shape_fun': PulseShapes.gaussian, - 'cutoff': 2, - 'drag_scaling': 0, - 'sigma': 5e-9, - 'riseFall': 20e-9}) - gate_chan = Instance((str, LogicalMarkerChannel)) - frequency = Float(0.0).tag( - desc='modulation frequency of the channel (can be positive or negative)') - - def __init__(self, **kwargs): - super(Edge, self).__init__(**kwargs) - - def isforward(self, source, target): - ''' Test whether (source, target) matches the directionality of the edge. ''' - nodes = (self.source, self.target) - if (source not in nodes) or (target not in nodes): - raise ValueError('One of {0} is not a node in the edge'.format(( - source, target))) - if (self.source, self.target) == (source, target): - return True - else: - return False - - -NewLogicalChannelList = [Qubit, Edge, LogicalMarkerChannel, Measurement] -NewPhysicalChannelList = [ - PhysicalMarkerChannel, - PhysicalQuadratureChannel, - ReceiverChannel -] +from bbndb.qgl import * \ No newline at end of file diff --git a/QGL/Compiler.py b/QGL/Compiler.py index 599e8d18..f6538f88 100644 --- a/QGL/Compiler.py +++ b/QGL/Compiler.py @@ -24,30 +24,34 @@ from functools import reduce from importlib import import_module import json - from . import config from . import PatternUtils from .PatternUtils import flatten, has_gate from . import Channels from . import ChannelLibraries from . import PulseShapes -from .PulsePrimitives import Id +from . import PulsePrimitives +from .PulsePrimitives import Id, clear_pulse_cache from .PulseSequencer import Pulse, PulseBlock, CompositePulse from . import ControlFlow from . import BlockLabel from . import TdmInstructions # only for APS2-TDM +from . import APS2CustomInstructions +from .RandomCliffordTools import default_clifford_options, VALID_CLIFFORD_TYPES +from . import RandomCliffordTools +import gc logger = logging.getLogger(__name__) def map_logical_to_physical(wires): - # construct a mapping of physical channels to lists of logical channels - # (there will be more than one logical channel if multiple logical - # channels share a physical channel) + """construct a mapping of physical channels to lists of logical channels + (there will be more than one logical channel if multiple logical + channels share a physical channel)""" physicalChannels = {} for logicalChan in wires.keys(): phys_chan = logicalChan.phys_chan if not phys_chan: - raise ValueError("LogicalChannel {} does not have a PhysicalChannel".format(phys_chan)) + raise ValueError("LogicalChannel {} does not have a PhysicalChannel".format(logicalChan)) if phys_chan not in physicalChannels: physicalChannels[phys_chan] = [logicalChan] else: @@ -101,7 +105,7 @@ def merge_channels(wires, channels): [e.amp * e.frequency for e in entries])[0] assert len(nonZeroSSBChan) <= 1, \ "Unable to handle merging more than one non-zero entry with non-zero frequency." - if nonZeroSSBChan: + if nonZeroSSBChan.size > 0: frequency = entries[nonZeroSSBChan[0]].frequency else: frequency = 0.0 @@ -221,6 +225,10 @@ def generate_waveforms(physicalWires): for pulse in flatten(wire): if not isinstance(pulse, Pulse): continue + if pulse.isRunTime: + #skip run-time pulses as we need to add the set of all possible pulses to + #the waveform table + continue if pulse.hashshape() not in wfs[ch]: if pulse.isTimeAmp: wfs[ch][pulse.hashshape()] = np.ones(1, dtype=np.complex) @@ -228,6 +236,69 @@ def generate_waveforms(physicalWires): wfs[ch][pulse.hashshape()] = pulse.shape return wfs +def get_clifford_type(wire, allowed_types=VALID_CLIFFORD_TYPES): + rt_pulses = [] + for pulse in flatten(wire): + if isinstance(pulse, Pulse) and pulse.isRunTime: + rt_pulses.append(pulse) + elif isinstance(pulse, PulseBlock) and pulse.isRunTime: + for p in pulse.pulses.values(): + if p.isRunTime: + rt_pulses.append(p) + + if len(rt_pulses) == 0: + return None + pulse_type = list(set([pulse.label for pulse in rt_pulses])) + #Remove pulses that are not the actual cliffords we want to play. + #We assume the RandomInverse is of the same type as the RandomCliffords! + for p in ('RandomInverse', 'RandomInverseReset'): + if p in pulse_type: + pulse_type.remove(p) + pulse_logical_chan = list(set([pulse.channel for pulse in rt_pulses])) + if len(pulse_type) > 1: + raise Exception(f"All run-time pulses must have the same label. Found: {pulse_type}.") + if len(pulse_logical_chan) > 1: + raise Exception(f"Found more than one channel per run-time pulse set: {pulse_logical_chan}.") + if pulse_type[0] not in allowed_types: + raise Exception(f"Unknown run time pulse type {pulse_type}.") + pulse_fn = getattr(PulsePrimitives, pulse_type[0].split('Random')[-1], None) + if pulse_fn is None: + raise Exception("Was unable to get pulse type for run-time generated pulses.") + return lambda x: pulse_fn(pulse_logical_chan[0], x) + + +def add_runtime_pulse_set(physicalWires, wfs): + for ch, wire in physicalWires.items(): + pulse_fn = get_clifford_type(wire) + if pulse_fn is None: + continue + all_pulses = [] + all_cliffords = [pulse_fn(n) for n in range(24)] + #Some could be CompositePulses so crack into indvidual pulses + for cliff in all_cliffords: + try: + for p in cliff.pulses: + all_pulses.append(p) + except AttributeError: + all_pulses.append(cliff) + + for cp in all_pulses: #make all-pulses a set? + if cp.hashshape() not in wfs[ch]: #don't duplicate data + if cp.isTimeAmp: + wfs[ch][cp.hashshape()] = np.ones(1, dtype=np.complex) + else: + wfs[ch][cp.hashshape()] = cp.shape + + return wfs + +def create_clifford_waveforms(physicalWires): + clifford_sets = {} + for ch, wire in physicalWires.items(): + pulse_fn = get_clifford_type(wire) + if pulse_fn is None: + continue + clifford_sets[ch] = [[Waveform(pulse_fn(n))] for n in range(24)] + return clifford_sets def pulses_to_waveforms(physicalWires): logger.debug("Converting pulses_to_waveforms:") @@ -276,7 +347,8 @@ def bundle_wires(physWires, wfs): awgData = setup_awg_channels(physWires.keys()) for chan in physWires.keys(): _, awgChan = chan.label.rsplit('-', 1) - awgChan = 'ch' + awgChan + if awgChan[0] != 'm': + awgChan = 'ch' + awgChan awgData[chan.instrument][awgChan]['linkList'] = physWires[chan] awgData[chan.instrument][awgChan]['wfLib'] = wfs[chan] if hasattr(chan, 'correctionT'): @@ -299,31 +371,13 @@ def collect_specializations(seqs): done.append(target) return funcs +def compile_to_IR(seqs, add_slave_trigger=True, tdm_seq=False, random_cliffords=False, + clifford_options=default_clifford_options): -def compile_to_hardware(seqs, - fileName, - suffix='', - axis_descriptor=None, - add_slave_trigger=True, - extra_meta=None, - tdm_seq = False): - ''' - Compiles 'seqs' to a hardware description and saves it to 'fileName'. - Other inputs: - suffix (optional): string to append to end of fileName, e.g. with - fileNames = 'test' and suffix = 'foo' might save to test-APSfoo.h5 - axis_descriptor (optional): a list of dictionaries describing the effective - axes of the measurements that the sequence will yield. For instance, - if `seqs` generates a Ramsey experiment, axis_descriptor would describe - the time delays between pulses. - add_slave_trigger (optional): add the slave trigger(s) - tdm_seq (optional): compile for TDM - ''' + ChannelLibraries.channelLib.update_channelDict() + clear_pulse_cache() logger.debug("Compiling %d sequence(s)", len(seqs)) - # save input code to file - save_code(seqs, fileName + suffix) - # all sequences should start with a WAIT for synchronization for seq in seqs: if not isinstance(seq[0], ControlFlow.Wait): @@ -331,11 +385,11 @@ def compile_to_hardware(seqs, seq.insert(0, ControlFlow.Wait()) # Add the digitizer trigger to measurements - logger.debug("Adding digitizer trigger") + logger.info("Adding digitizer trigger") PatternUtils.add_digitizer_trigger(seqs) # Add gating/blanking pulses - logger.debug("Adding blanking pulses") + logger.info("Adding blanking pulses") for seq in seqs: PatternUtils.add_gate_pulses(seq) @@ -345,23 +399,25 @@ def compile_to_hardware(seqs, PatternUtils.add_slave_trigger(seqs, ChannelLibraries.channelLib['slave_trig']) else: - logger.debug("Not adding slave trigger") + logger.info("Not adding slave trigger") # find channel set at top level to account for individual sequence channel variability + logger.info("Finding unique channels.") channels = set() for seq in seqs: channels |= find_unique_channels(seq) # Compile all the pulses/pulseblocks to sequences of pulses and control flow - wireSeqs = compile_sequences(seqs, channels) + logger.info("Compiling sequences.") + wireSeqs = compile_sequences(seqs, channels, random_cliffords=random_cliffords, clifford_options=clifford_options) if not validate_linklist_channels(wireSeqs.keys()): print("Compile to hardware failed") return - logger.debug('') logger.debug("Now after gating constraints:") # apply gating constraints + logger.info("Applying gating constraints") for chan, seq in wireSeqs.items(): if isinstance(chan, Channels.LogicalMarkerChannel): wireSeqs[chan] = PatternUtils.apply_gating_constraints( @@ -369,6 +425,7 @@ def compile_to_hardware(seqs, debug_print(wireSeqs, 'Gated sequence') # save number of measurements for meta info + logger.info("Counting measurements.") num_measurements = count_measurements(wireSeqs) wire_measurements = count_measurements_per_wire(wireSeqs) @@ -376,52 +433,104 @@ def compile_to_hardware(seqs, # PhysicalQuadratureChannels and PhysicalMarkerChannels # for the APS, the naming convention is: # ASPName-12, or APSName-12m1 + logger.info("Mapping logical to physical channels.") physWires = map_logical_to_physical(wireSeqs) # Pave the way for composite instruments, not useful yet... - files = {} - label_to_inst = {} - label_to_chan = {} - old_wire_names = {} - old_wire_instrs = {} + extra_info = {} + extra_info["files"] = {} + extra_info["label_to_inst"] = {} + extra_info["label_to_chan"] = {} + extra_info["old_wire_names"] = {} + extra_info["old_wire_instrs"] = {} + + extra_info["num_measurements"] = num_measurements + extra_info["wire_measurements"] = wire_measurements + extra_info["channels"] = channels + for wire, pulses in physWires.items(): pattern_module = import_module('QGL.drivers.' + wire.translator) if pattern_module.SEQFILE_PER_CHANNEL: - inst_name = pattern_module.get_true_inst_name(wire.label) - chan_name = pattern_module.get_true_chan_name(wire.label) + inst_name = wire.transmitter.label + chan_name = wire.label has_non_id_pulses = any([len([p for p in ps if isinstance(p,Pulse) and p.label!="Id"]) > 0 for ps in pulses]) - label_to_inst[wire.label] = inst_name + extra_info["label_to_inst"][wire.label] = inst_name if has_non_id_pulses: - label_to_chan[wire.label] = chan_name + extra_info["label_to_chan"][wire.label] = chan_name # Change the name/inst for uniqueness, but we must restore this later! - old_wire_names[wire] = wire.label - old_wire_instrs[wire] = wire.instrument + extra_info["old_wire_names"][wire] = wire.label + extra_info["old_wire_instrs"][wire] = wire.instrument wire.instrument = wire.label wire.label = chan_name - files[inst_name] = {} + extra_info["files"][inst_name] = {} # construct channel delay map + logger.info("Constructing delay map.") delays = channel_delay_map(physWires) # apply delays + logger.info("Applying delays.") for chan, wire in physWires.items(): PatternUtils.delay(wire, delays[chan]) debug_print(physWires, 'Delayed wire') # generate wf library (base shapes) + logger.info("Generating waveform library.") wfs = generate_waveforms(physWires) + # If there are run-time pulses add these to the library + if random_cliffords: + wfs = add_runtime_pulse_set(physWires, wfs) + # replace Pulse objects with Waveforms + logger.info("Replacing pulses with waveforms") physWires = pulses_to_waveforms(physWires) # bundle wires on instruments, or channels depending # on whether we have one sequence per channel + logger.info("Bundling wires.") awgData = bundle_wires(physWires, wfs) + return awgData, extra_info + +def compile_to_hardware(seqs, + fileName, + library_version=None, + suffix='', + axis_descriptor=None, + add_slave_trigger=True, + extra_meta=None, + tdm_seq = False): + ''' + Compiles 'seqs' to a hardware description and saves it to 'fileName'. + Other inputs: + library_version (optional): string or ChannelLibrary instance to pack in the + metafile. This will be the version of the library loaded during program + execution. Default None uses the current working version. + suffix (optional): string to append to end of fileName, e.g. with + fileNames = 'test' and suffix = 'foo' might save to test-APSfoo.h5 + axis_descriptor (optional): a list of dictionaries describing the effective + axes of the measurements that the sequence will yield. For instance, + if `seqs` generates a Ramsey experiment, axis_descriptor would describe + the time delays between pulses. + add_slave_trigger (optional): add the slave trigger(s) + tdm_seq (optional): compile for TDM + ''' + # save input code to file + + save_code(seqs, fileName + suffix) + + if any([p.isRunTime for p in flatten(seqs)]): + random_cliffords = True + else: + random_cliffords = False + + awgData, extra_info = compile_to_IR(seqs, add_slave_trigger=add_slave_trigger, tdm_seq=tdm_seq, random_cliffords=random_cliffords) # convert to hardware formats # files = {} awg_metas = {} - for awgName, data in awgData.items(): + for awgName in list(awgData.keys()): + data = awgData[awgName] # create the target folder if it does not exist targetFolder = os.path.split(os.path.normpath(os.path.join( config.AWGDir, fileName)))[0] @@ -430,16 +539,23 @@ def compile_to_hardware(seqs, fullFileName = os.path.normpath(os.path.join( config.AWGDir, fileName + '-' + awgName + suffix + data[ 'seqFileExt'])) + logger.info("Writing sequence file for: {}".format(awgName)) new_meta = data['translator'].write_sequence_file(data, fullFileName) if new_meta: awg_metas[awgName] = new_meta + ChannelLibraries.channelLib[awgName].extra_meta = new_meta # Allow for per channel and per AWG seq files - if awgName in label_to_inst: - if awgName in label_to_chan: - files[label_to_inst[awgName]][label_to_chan[awgName]] = fullFileName + if awgName in extra_info["label_to_inst"]: + if awgName in extra_info["label_to_chan"]: + files[extra_info["label_to_inst"][awgName]][extra_info["label_to_chan"][awgName]] = fullFileName else: - files[awgName] = fullFileName + extra_info["files"][awgName] = fullFileName + + del data + del awgData[awgName] + gc.collect() + # generate TDM sequences FIXME: what's the best way to identify the need for a TDM seq.? Support for single TDM if tdm_seq and 'APS2Pattern' in [wire.translator for wire in physWires]: aps2tdm_module = import_module('QGL.drivers.APS2Pattern') # this is redundant with above @@ -454,22 +570,31 @@ def compile_to_hardware(seqs, else: extra_meta = awg_metas # create meta output + db_info = { + 'db_provider': ChannelLibraries.channelLib.db_provider, + 'db_resource_name': ChannelLibraries.channelLib.db_resource_name, + 'library_name': 'working', + 'library_id': ChannelLibraries.channelLib.channelDatabase.id + } if not axis_descriptor: axis_descriptor = [{ 'name': 'segment', 'unit': None, - 'points': list(range(1, 1 + num_measurements)), + 'points': list(range(1, 1 + extra_info["num_measurements"])), 'partition': 1 }] receiver_measurements = {} - for wire, n in wire_measurements.items(): + for wire, n in extra_info["wire_measurements"].items(): if wire.receiver_chan and n>0: receiver_measurements[wire.receiver_chan.label] = n meta = { - 'instruments': files, + 'database_info': db_info, + 'instruments': extra_info["files"], 'num_sequences': len(seqs), - 'num_measurements': num_measurements, + 'num_measurements': extra_info["num_measurements"], 'axis_descriptor': axis_descriptor, + 'qubits': [c.label for c in extra_info["channels"] if isinstance(c, Channels.Qubit)], + 'measurements': [c.label for c in extra_info["channels"] if isinstance(c, Channels.Measurement)], 'receivers': receiver_measurements } if extra_meta: @@ -479,16 +604,17 @@ def compile_to_hardware(seqs, json.dump(meta, FID, indent=2, sort_keys=True) # Restore the wire info - for wire in old_wire_names.keys(): - wire.label = old_wire_names[wire] - for wire in old_wire_instrs.keys(): - wire.instrument = old_wire_instrs[wire] + for wire in extra_info["old_wire_names"].keys(): + wire.label = extra_info["old_wire_names"][wire] + for wire in extra_info["old_wire_instrs"].keys(): + wire.instrument = extra_info["old_wire_instrs"][wire] # Return the filenames we wrote return metafilepath -def compile_sequences(seqs, channels=set()): +def compile_sequences(seqs, channels=set(), random_cliffords=False, + clifford_options=default_clifford_options): ''' Main function to convert sequences to miniLL's and waveform libraries. ''' @@ -502,6 +628,23 @@ def compile_sequences(seqs, channels=set()): subroutines = collect_specializations(seqs) seqs += subroutines + if random_cliffords: + + qubits = [q for q in list(channels) if isinstance(q, Channels.Qubit)] + if len(qubits) > 1: + raise Exception("Too many qubits! Don't know how to deal with this yet.") + #replace cliffords with + cliffords = [[get_clifford_type(seqs)(n)] for n in range(24)] + jt_label = RandomCliffordTools.generate_clifford_jump_table(cliffords) + RandomCliffordTools.insert_clifford_calls(seqs, jt_label=jt_label, clifford_options=clifford_options) + + # if not isinstance(seqs[0][0], BlockLabel.BlockLabel): + # raise Exception("Fist instruciton must be block label!") + # start_label = seqs[0][0] + seqs += cliffords + #seqs[0:0] = cliffords + #seqs[0].insert(0, ControlFlow.Goto(start_label)) + #expand the channel definitions for anything defined in subroutines for func in subroutines: channels |= find_unique_channels(subroutines) @@ -564,9 +707,8 @@ def flatten_to_pulses(obj): continue # control flow broadcasts to all channels if channel attribute is None if (isinstance(block, ControlFlow.ControlInstruction) or - isinstance(block, TdmInstructions.WriteAddrInstruction) or - isinstance(block, TdmInstructions.CustomInstruction) or - isinstance(block, TdmInstructions.LoadCmpVramInstruction)): + isinstance(block, TdmInstructions.VRAMInstruction) or + isinstance(block, TdmInstructions.CustomInstruction)): # Need to deal with attaching measurements and edges to control # instruction. Until we have a proper solution for that, we will # always broadcast control instructions to all channels @@ -575,6 +717,9 @@ def flatten_to_pulses(obj): for chan in block_channels: wires[chan] += [copy(block)] continue + #Don't propagate VRAM instructions + #if isinstance(block, TdmInstructions.VRAMInstruction) or isinstance(block, TdmInstructions.CustomInstruction): + # continue # propagate frame change from nodes to edges for chan in channels: if block.pulses[chan].frameChange == 0: @@ -584,7 +729,14 @@ def flatten_to_pulses(obj): wires = propagate_node_frame_to_edges( wires, chan, block.pulses[chan].frameChange) # drop length 0 blocks but push nonzero frame changes onto previous entries - if block.length == 0: + + is_subroutine = False + if isinstance(seq[-1], ControlFlow.Return): + #Make sure we do not drop frame update instructions for subroutines that are only Z pulses + is_subroutine = True + + + if block.length == 0 and not is_subroutine: for chan in channels: if block.pulses[chan].frameChange == 0: continue @@ -656,11 +808,29 @@ def normalize(seq, channels=None): block.pulses[ch] = Id(ch, blocklen) return seq +class MemoizedObject(type): + """Metaclass for memoizing objects. Designed to save memory when processing + very long sequences. Overrides __call__ to prevent creating a new instance. + Idea from https://stackoverflow.com/questions/47785795/memoized-objects-still-have-their-init-invoked + """ + def __init__(self, name, bases, namespace): + super().__init__(name, bases, namespace) + self.cache = {} + def __call__(self, pulse=None): + hash = pulse.hashshape() + if pulse is not None and hash not in self.cache: + self.cache[hash] = super().__call__(pulse=pulse) + return self.cache[hash] + class Waveform(object): """ Simplified channel independent version of a Pulse with a key into waveform library. """ + #Use slots to create attributes to save on memory. + __slots__ = ["label", "key", "amp", "length", "phase", "frameChange", + "isTimeAmp", "frequency", "logicalChan", "maddr", "startTime", + "isRunTime"] def __init__(self, pulse=None): if pulse is None: @@ -674,6 +844,7 @@ def __init__(self, pulse=None): self.frequency = 0 self.logicalChan = "" self.maddr = (-1, 0) + self.isRunTime = False else: self.label = pulse.label self.key = pulse.hashshape() @@ -685,11 +856,14 @@ def __init__(self, pulse=None): self.frequency = pulse.frequency self.logicalChan = pulse.channel self.maddr = pulse.maddr + self.isRunTime = pulse.isRunTime def __repr__(self): return self.__str__() def __str__(self): + if self.isRunTime: + return f"Hardware-Generated({self.label}, {self.length})" if self.isTimeAmp: TA = 'HIGH' if self.amp != 0 else 'LOW' return "Waveform-TA(" + TA + ", " + str(self.length) + ")" @@ -698,15 +872,18 @@ def __str__(self): self.key)[:6] + ", " + str(self.length) + ")" def __eq__(self, other): + if self.isRunTime or other.isRunTime: + return False if isinstance(other, self.__class__): - return self.__dict__ == other.__dict__ + #No __dict__ property so we check all properties. + return all((getattr(self, attr, None) == getattr(other, attr, None) for attr in self.__slots__)) return False def __ne__(self, other): return not self == other def __hash__(self): - return hash(frozenset(self.__dict__.items())) + return hash(frozenset((attr, getattr(self, attr, None)) for attr in self.__slots__)) @property def isZero(self): diff --git a/QGL/ControlFlow.py b/QGL/ControlFlow.py index 719a2964..692958ff 100644 --- a/QGL/ControlFlow.py +++ b/QGL/ControlFlow.py @@ -151,8 +151,16 @@ def __init__(self, target): class Call(ControlInstruction): # target is a BlockLabel - def __init__(self, target): + def __init__(self, target, indirect=False): super(Call, self).__init__("CALL", target=target) + self.indirect = indirect + + def __str__(self): + if not self.indirect: + return f"{self.instruction}({str(self.target)})" + else: + return f"{self.instruction}({str(self.target)}, INDIRECT)" + class Return(ControlInstruction): diff --git a/QGL/GSTTools.py b/QGL/GSTTools.py index fda0a579..49ad9749 100644 --- a/QGL/GSTTools.py +++ b/QGL/GSTTools.py @@ -23,13 +23,19 @@ from .Cliffords import * from .BasicSequences.helpers import create_cal_seqs from .Compiler import compile_to_hardware -from pygsti.objects import GateString from itertools import chain from random import choices +PYGSTI_PRESENT = False +try: + from pygsti.objects.circuit import Circuit + PYGSTI_PRESENT = True +except: + pass + #Default mapping from pyGSTi naming convention to QGL gates. -gst_gate_map = {"Gx": X, - "Gy": Y, +gst_gate_map = {"Gx": X90, + "Gy": Y90, "Gi": Id} def gst_map_1Q(gst_list, qubit, qgl_map=gst_gate_map, append_meas=True): @@ -45,11 +51,11 @@ def gst_map_1Q(gst_list, qubit, qgl_map=gst_gate_map, append_meas=True): Returns: QGL sequences, preserving the input list nesting (as a generator) """ - if isinstance(gst_list, GateString): + if isinstance(gst_list, Circuit): gst_list = [gst_list] for item in gst_list: - if isinstance(item, GateString): - mapped = map(lambda x: qgl_map[x](qubit), item.tup) + if isinstance(item, Circuit): + mapped = map(lambda x: qgl_map[str(x)](qubit), item.tup) if append_meas: yield list(chain(mapped, [MEAS(qubit)])) else: @@ -57,6 +63,31 @@ def gst_map_1Q(gst_list, qubit, qgl_map=gst_gate_map, append_meas=True): elif isinstance(item, list): yield list(gst_map_1Q(item, qubit, qgl_map=qgl_map, append_meas=append_meas)) +def gst_map_2Q(gst_list, qubits, qgl_map=None, append_meas=False): + """ + Helper function that takes an arbitrarily nested list of pygsti gatestrings + and converts them into QGL sequences, keeping the same nesting of lists. + + Inputs: + gst_list: GateString to convert, or possibly nested list of pyGSTi GateStrings. + qubit: QGL qubit to apply the sequence to + qgl_map: Dictionary that maps between pyGSTi "Gx" string to QGL pulse + append_meas: Append a measurement to each sequence. + Returns: + QGL sequences, preserving the input list nesting (as a generator) + """ + if isinstance(gst_list, GateString): + gst_list = [gst_list] + for item in gst_list: + if isinstance(item, GateString): + mapped = map(lambda x: qgl_map[x], item.tup) + if append_meas: + yield list(chain(mapped, [reduce(lambda x,y: x*y, map(MEAS, qubits))])) + else: + yield list(mapped) + elif isinstance(item, list): + yield list(gst_map_2Q(item, qubit, qgl_map=qgl_map, append_meas=append_meas)) + def create_gst_sequence_from_pygsti(gst_list, qubit, gate_map=gst_gate_map): """ Returns list of QGL sequences from a pyGSTi GateString list. See gst_map_1Q. The return value is a list of sequences that can be complied by QGL. diff --git a/QGL/PatternUtils.py b/QGL/PatternUtils.py index 9748b35d..0719a3e0 100644 --- a/QGL/PatternUtils.py +++ b/QGL/PatternUtils.py @@ -202,12 +202,17 @@ def add_digitizer_trigger(seqs): #find corresponding digitizer trigger chanlist = list(flatten([seq[ct].channel])) for chan in chanlist: - if hasattr(chan, 'trig_chan'): + if hasattr(chan, 'trig_chan') and chan.trig_chan is not None: trig_chan = chan.trig_chan if not (hasattr(seq[ct], 'pulses') and trig_chan in seq[ct].pulses.keys()): seq[ct] = align('left', seq[ct], TAPulse("TRIG", trig_chan, trig_chan.pulse_params['length'], 1.0, 0.0, 0.0)) +def contains_runtime_pulses(seqs): + """ + Determines if sequences contain run-time generated pulses. + """ + return any([hasattr(entry, 'isRunTime') and entry.isRunTime for entry in flatten(seqs)]) def contains_measurement(entry): """ @@ -334,5 +339,5 @@ def flatten_pulses(): awg, [str(p) for p in ps.values()])) continue print("Updating pulses for {}".format(awg)) - translators[awg].update_wf_library(path + "-" + awg + ".h5", ps, + translators[awg].update_wf_library(path + "-" + awg + ".aps", ps, offsets) diff --git a/QGL/Plotting.py b/QGL/Plotting.py index 25c3c1a5..8051cb7d 100644 --- a/QGL/Plotting.py +++ b/QGL/Plotting.py @@ -22,29 +22,10 @@ ''' import os.path, uuid, tempfile -import bokeh.plotting as bk -from bokeh.layouts import column -from bokeh.util.warnings import BokehUserWarning -from bokeh.resources import INLINE import numpy as np import warnings from . import config -def output_notebook(local=True, suppress_warnings=False): - if suppress_warnings: - warnings.simplefilter("ignore", BokehUserWarning) - if local: - bk.output_notebook(resources=INLINE) - else: - bk.output_notebook() - -def output_file(local=True, suppress_warnings=True): - if suppress_warnings: - warnings.simplefilter("ignore", BokehUserWarning) - mode = "inline" if local else "cdn" - bk.output_file(os.path.join(tempfile.gettempdir(), str(uuid.uuid4()) + - ".html"), mode=mode) - def build_waveforms(seq): # import here to avoid circular imports from . import Compiler, PulseSequencer, BlockLabel, ControlFlow @@ -76,30 +57,30 @@ def build_waveforms(seq): concatShapes[q] = np.append(concatShapes[q], 0) return concatShapes - -def plot_waveforms(waveforms, figTitle=''): - channels = waveforms.keys() - # plot - plots = [] - for (ct, chan) in enumerate(channels): - fig = bk.figure(title=figTitle + repr(chan), - plot_width=800, - plot_height=350, - y_range=[-1.05, 1.05], - x_axis_label=u'Time (μs)') - fig.background_fill_color = config.plotBackground - if config.gridColor: - fig.xgrid.grid_line_color = config.gridColor - fig.ygrid.grid_line_color = config.gridColor - waveformToPlot = waveforms[chan] - xpts = np.linspace(0, len(waveformToPlot) / chan.phys_chan.sampling_rate - / 1e-6, len(waveformToPlot)) - fig.line(xpts, np.real(waveformToPlot), color='red') - fig.line(xpts, np.imag(waveformToPlot), color='blue') - plots.append(fig) - bk.show(column(*plots)) - - -def show(seq): - waveforms = build_waveforms(seq) - plot_waveforms(waveforms) +# +# def plot_waveforms(waveforms, figTitle=''): +# channels = waveforms.keys() +# # plot +# plots = [] +# for (ct, chan) in enumerate(channels): +# fig = bk.figure(title=figTitle + repr(chan), +# plot_width=800, +# plot_height=350, +# y_range=[-1.05, 1.05], +# x_axis_label=u'Time (μs)') +# fig.background_fill_color = config.plotBackground +# if config.gridColor: +# fig.xgrid.grid_line_color = config.gridColor +# fig.ygrid.grid_line_color = config.gridColor +# waveformToPlot = waveforms[chan] +# xpts = np.linspace(0, len(waveformToPlot) / chan.phys_chan.sampling_rate +# / 1e-6, len(waveformToPlot)) +# fig.line(xpts, np.real(waveformToPlot), color='red') +# fig.line(xpts, np.imag(waveformToPlot), color='blue') +# plots.append(fig) +# bk.show(column(*plots)) + +# +# def show(seq): +# waveforms = build_waveforms(seq) +# plot_waveforms(waveforms) diff --git a/QGL/PulsePrimitives.py b/QGL/PulsePrimitives.py index 59d48099..b9d66f2a 100644 --- a/QGL/PulsePrimitives.py +++ b/QGL/PulsePrimitives.py @@ -24,13 +24,15 @@ from .PulseSequencer import Pulse, TAPulse, CompoundGate, align from functools import wraps, reduce - -def overrideDefaults(chan, updateParams): +def overrideDefaults(chan, updateParams, ignoredStrParams=['isRunTime', 'maddr', 'moffset']): '''Helper function to update any parameters passed in and fill in the defaults otherwise.''' # The default parameter list depends on the channel type so pull out of channel # Then update passed values paramDict = chan.pulse_params.copy() paramDict.update(updateParams) + for param in ignoredStrParams: + if param in paramDict.keys(): + paramDict.pop(param) return paramDict @@ -91,6 +93,10 @@ def Utheta(qubit, del params["amp"] if "phase" in params: del params["phase"] + if "frequency" in kwargs: + frequency = kwargs["frequency"] + else: + frequency = None # allow override of angle -> amplitude lookup if the user provides an "amp" # keyword argument if "amp" in kwargs: @@ -109,7 +115,7 @@ def Utheta(qubit, else: # linearly scale based upon the 'pi/2' amplitude amp = (angle / (pi/2)) * qubit.pulse_params['pi2Amp'] - return Pulse(label, qubit, params, amp, phase, 0.0, ignoredStrParams) + return Pulse(label, qubit, params, amp, phase, 0.0, ignoredStrParams, frequency=frequency) # generic pulses around X, Y, and Z axes @@ -333,6 +339,57 @@ def arb_axis_drag(qubit, return Pulse(kwargs["label"] if "label" in kwargs else "ArbAxis", qubit, params, 1.0, aziAngle, frameChange) +def RandomCliff(qubit): + """A randomly generated clifford gate, using the standard clifford library. + """ + params = overrideDefaults(qubit, {}) + return Pulse("RandomCliff", qubit, params, isRunTime=True) + +def RandomAC(qubit): + """A randomly generated clifford gate, using the diatomic clifford library. + """ + params = overrideDefaults(qubit, {}) + return Pulse("RandomAC", qubit, params, isRunTime=True) + +def RandomDiAC(qubit): + """A randomly generated clifford gate, using the atomic clifford library. + """ + params = overrideDefaults(qubit, {}) + params["length"] *= 2.0 + return Pulse("RandomDiAC", qubit, params, isRunTime=True) + +def RandomInverse(qubit): + """The currently-stored `Inverse` clifford generated by the on-board frame + tracking hardware. + """ + params = overrideDefaults(qubit, {}) + return Pulse("RandomInverse", qubit, params, isRunTime=True) + +def RandomInverseReset(qubit, reset_value=0): + """Reset the on-board frame tracker to the given value (clifford index). + NOTE: Because of potential timing issues with the random clifford firmware, + this "pulse" will be played in the "dead time" between sequences (i.e. + BEFORE the first WAIT of a sequence.) No guarantees as to what will happen if + you try to put this pulse inside of a sequence... + """ + params = overrideDefaults(qubit, {}) + #note that we store the reset value in the `maddr` paramter, otherwise unused + #TODO: this is a bit hacky and should probably be changed. + return Pulse("RandomInverseReset", qubit, params, isRunTime=True, maddr=reset_value) + +from . import Cliffords + +def RandomTestCliff(qubit): + params = overrideDefaults(qubit, {}) + return Pulse("RandomTestCliff", qubit, params, isRunTime=True) + +def TestCliff(qubit, cliffNum): + params = overrideDefaults(qubit, {'shape_fun': 'constant'}) + amp = cliffNum * (1.0/24.0) + (1.0/24.0) + return Pulse("TCPulse", qubit, params, amp, 0.0, 0.0, frequency=0.0) + +def Cliff(qubit, cliffNum): + return reduce(operator.add, [p for p in Cliffords.clifford_seq(cliffNum, qubit)]) def AC(qubit, cliffNum): """ @@ -357,7 +414,7 @@ def AC(qubit, cliffNum): #Now a big else if chain for to get the specific Clifford if cliffNum == 0: #Identity gate - return Id(qubit, length=0) + return Id(qubit)#Id(qubit, length=0) elif cliffNum == 1: #X90 return X90(qubit) diff --git a/QGL/PulseSequencePlotter.py b/QGL/PulseSequencePlotter.py index e2b14ed5..27b61d87 100644 --- a/QGL/PulseSequencePlotter.py +++ b/QGL/PulseSequencePlotter.py @@ -25,12 +25,6 @@ import os.path import json from importlib import import_module -from bokeh.layouts import column -from bokeh.models import CustomJS, ColumnDataSource, Slider -from bokeh.plotting import Figure, show -from bokeh.palettes import d3, brewer, Inferno - -from jinja2 import Template import numpy as np from . import config @@ -71,14 +65,14 @@ def resolve_translator(filename, translators): raise NameError("No translator found to open the given file %s", filename) -def plot_pulse_files(metafile, time=False): +def plot_pulse_files(metafile, time=True, backend='bqplot'): ''' plot_pulse_files(metafile) - Helper function to plot a list of AWG files. A JS slider allows choice of sequence number. + Helper function to plot a list of AWG files. A jupyter slider widget allows choice of sequence number. ''' #If we only go one filename turn it into a list - + with open(metafile, 'r') as FID: meta_info = json.load(FID) fileNames = [] @@ -94,67 +88,45 @@ def plot_pulse_files(metafile, time=False): localname = os.path.split(fileNames[0])[1] sequencename = localname.split('-')[0] - data = {line_name: ColumnDataSource(data=dat) for line_name,dat in data_dicts.items()} - plot = Figure(title=sequencename, plot_width=1000) - if config.plotBackground: - plot.background_fill_color = config.plotBackground - if config.gridColor: - plot.xgrid.grid_line_color = config.gridColor - plot.ygrid.grid_line_color = config.gridColor - - if len(line_names) < 10: - # Colobrewer2 qualitative Set1 (http://colorbrewer2.org) - colors = brewer['Set1'][max(3, len(line_names))] - elif 9 < len(line_names) < 19: - # d3 Category20 for up to 18 channels - colors = d3['Category20'][len(line_names)] - else: - # 256 palette - colors = [Inferno[256][np.int(ct-1)] for ct in np.floor(np.linspace(0,256,len(line_names)))] - js_sources = data - for ct, k in enumerate(line_names): - k_ = k.replace("-", "_") - line = plot.line(data_dicts[k + "_1"]["x"], - data_dicts[k + "_1"]["y"], - color=colors[ct % len(colors)], - line_width=2, - legend=k.replace("_", "-")) - js_sources[k_] = line.data_source - - code_template = Template(""" - var seq_num = cb_obj.getv('value'); - // console.log(seq_num); - var all_data = { - {% for trace in trace_names %} - '{{trace}}': {{trace}}.getv('data'), - {% endfor %} - }; - {% for line in line_names %} - {{line}}['data'] = {'x': (all_data['{{line}}_'.concat(seq_num.toString())])['x'], - 'y': (all_data['{{line}}_'.concat(seq_num.toString())])['y']}; - {% endfor %} - """) - rendered = code_template.render( - line_names=line_names, - trace_names=list(data.keys())[:-len(line_names)] - ) - - callback = CustomJS( - args=dict(**js_sources), - code=rendered) - - if num_seqs > 1: - slider = Slider(start=1, - end=num_seqs, - value=1, - step=1, - title="Sequence", - callback=callback) - - layout = column(slider, plot) - show(layout) - else: - show(plot) + if backend=='matplotlib': + import matplotlib.pyplot as plt + from ipywidgets import interact, IntSlider + def update_plot(seq_ind): + for line_name in line_names: + dat = data_dicts[f"{line_name}_{seq_ind}"] + plt.plot(dat['x'], dat['y'], label=line_name, linewidth=1.0) + interact(update_plot, seq_ind=IntSlider(min=1,max=num_seqs,step=1,value=1,description="Sequence Number")) + + elif backend=='bqplot': + from bqplot import DateScale, LinearScale, Axis, Lines, Figure, Tooltip + from bqplot.colorschemes import CATEGORY10, CATEGORY20 + from ipywidgets import interact, IntSlider, VBox + sx = LinearScale() + sy = LinearScale(min=-1.0, max=2*len(line_names)-1.0) + if time: + ax = Axis(label='Time (ns)', scale=sx) + else: + ax = Axis(label="Samples", scale=sx) + ay = Axis(label='Amplitude', scale=sy, orientation='vertical') + + colors = CATEGORY10 if len(line_names)<10 else CATEGORY20 + lines = [] + tt = Tooltip(fields=['name'], labels=['Channel']) + x_mult = 1.0e9 if time else 1 + for i, line_name in enumerate(line_names): + dat = data_dicts[f"{line_name}_1"] + lines.append(Lines(labels=[line_name], x=x_mult*dat['x'], y=dat['y'], scales={'x': sx, 'y': sy}, + tooltip=tt, animate=False, colors=[colors[i]])) + + slider = IntSlider(min=1, max=num_seqs, step=1, description='Segment', value=1) + def segment_changed(change): + for line, line_name in zip(lines, line_names): + dat = data_dicts[f"{line_name}_{slider.value}"] + line.x = x_mult*dat['x'] + line.y = dat['y'] + slider.observe(segment_changed, 'value') + fig = Figure(marks=lines, axes=[ax, ay], title='Waveform Plotter',animation_duration=50) + return VBox([slider, fig]) def extract_waveforms(fileNames, nameDecorator='', time=False): @@ -166,8 +138,8 @@ def extract_waveforms(fileNames, nameDecorator='', time=False): # Assume a naming convention path/to/file/SequenceName-AWGName.h5 AWGName = "-".join((os.path.split(os.path.splitext(fileName)[0])[1]).split('-')[1:]) # Strip any _ suffix - if '_' in AWGName: - AWGName = AWGName[:AWGName.index('_')] + # if '_' in AWGName: + # AWGName = AWGName[:AWGName.index('_')] translator = resolve_translator(fileName, translators) wfs = translator.read_sequence_file(fileName) @@ -177,7 +149,7 @@ def extract_waveforms(fileNames, nameDecorator='', time=False): if all_zero_seqs(seqs): continue num_seqs = max(num_seqs, len(seqs)) - line_names.append((AWGName + nameDecorator + '_' + k).replace("-","_")) + line_names.append((AWGName + nameDecorator + '_' + k).replace("-","_")) k_ = line_names[-1].replace("-", "_") for ct, seq in enumerate(seqs): data_dicts[k_ + "_{:d}".format(ct + 1)] = {} @@ -193,101 +165,101 @@ def extract_waveforms(fileNames, nameDecorator='', time=False): return line_names, num_seqs, data_dicts -def plot_pulse_files_compare(metafile1, metafile2, time=False): - ''' - plot_pulse_files_compare(fileNames1, fileNames2) - - Helper function to plot a list of AWG files. A JS slider allows choice of sequence number. - ''' - #If we only go one filename turn it into a list - fileNames1 = [] - fileNames2 = [] - - with open(metafile1, 'r') as FID: - meta_info1 = json.load(FID) - - for el in meta_info1["instruments"].values(): - # Accomodate seq_file per instrument and per channel - if isinstance(el, str): - fileNames1.append(el) - elif isinstance(el, dict): - for file in el.values(): - fileNames1.append(file) - - with open(metafile2, 'r') as FID: - meta_info2 = json.load(FID) - - for el in meta_info2["instruments"].values(): - # Accomodate seq_file per instrument and per channel - if isinstance(el, str): - fileNames2.append(el) - elif isinstance(el, dict): - for file in el.values(): - fileNames2.append(file) - - line_names1, num_seqs1, data_dicts1 = extract_waveforms(fileNames1, 'A', time=time) - line_names2, num_seqs2, data_dicts2 = extract_waveforms(fileNames2, 'B', time=time) - num_seqs = max(num_seqs1, num_seqs2) - data_dicts1.update(data_dicts2) - line_names = line_names1 + line_names2 - - localname = os.path.split(fileNames1[0])[1] - sequencename = localname.split('-')[0] - - data = {line_name: ColumnDataSource(data=dat) for line_name,dat in data_dicts1.items()} - plot = Figure(title=sequencename, plot_width=1000) - plot.background_fill_color = config.plotBackground - if config.gridColor: - plot.xgrid.grid_line_color = config.gridColor - plot.ygrid.grid_line_color = config.gridColor - - # Colobrewer2 qualitative Set1 (http://colorbrewer2.org) - colours = [ - "#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", - "#a65628", "#f781bf", "#999999" - ] - - js_sources = data - for ct, k in enumerate(line_names): - k_ = k.replace("-", "_") - line = plot.line(data_dicts1[k + "_1"]["x"], - data_dicts1[k + "_1"]["y"], - color=colours[ct % len(colours)], - line_width=2, - legend=k.replace("_", "-")) - js_sources[k_] = line.data_source - - code_template = Template(""" - var seq_num = cb_obj.getv('value'); - // console.log(seq_num); - var all_data = { - {% for trace in trace_names %} - '{{trace}}': {{trace}}.getv('data'), - {% endfor %} - }; - {% for line in line_names %} - {{line}}['data'] = {'x': (all_data['{{line}}_'.concat(seq_num.toString())])['x'], - 'y': (all_data['{{line}}_'.concat(seq_num.toString())])['y']}; - {% endfor %} - """) - rendered = code_template.render( - line_names=line_names, - trace_names=list(data.keys())[:-len(line_names)] - ) - - callback = CustomJS( - args=dict(**js_sources), - code=rendered) - - if num_seqs > 1: - slider = Slider(start=1, - end=num_seqs, - value=1, - step=1, - title="Sequence", - callback=callback) - - layout = column(slider, plot) - show(layout) - else: - show(plot) +# def plot_pulse_files_compare(metafile1, metafile2, time=False): +# ''' +# plot_pulse_files_compare(fileNames1, fileNames2) + +# Helper function to plot a list of AWG files. A JS slider allows choice of sequence number. +# ''' +# #If we only go one filename turn it into a list +# fileNames1 = [] +# fileNames2 = [] + +# with open(metafile1, 'r') as FID: +# meta_info1 = json.load(FID) + +# for el in meta_info1["instruments"].values(): +# # Accomodate seq_file per instrument and per channel +# if isinstance(el, str): +# fileNames1.append(el) +# elif isinstance(el, dict): +# for file in el.values(): +# fileNames1.append(file) + +# with open(metafile2, 'r') as FID: +# meta_info2 = json.load(FID) + +# for el in meta_info2["instruments"].values(): +# # Accomodate seq_file per instrument and per channel +# if isinstance(el, str): +# fileNames2.append(el) +# elif isinstance(el, dict): +# for file in el.values(): +# fileNames2.append(file) + +# line_names1, num_seqs1, data_dicts1 = extract_waveforms(fileNames1, 'A', time=time) +# line_names2, num_seqs2, data_dicts2 = extract_waveforms(fileNames2, 'B', time=time) +# num_seqs = max(num_seqs1, num_seqs2) +# data_dicts1.update(data_dicts2) +# line_names = line_names1 + line_names2 + +# localname = os.path.split(fileNames1[0])[1] +# sequencename = localname.split('-')[0] + +# data = {line_name: ColumnDataSource(data=dat) for line_name,dat in data_dicts1.items()} +# plot = Figure(title=sequencename, plot_width=1000) +# plot.background_fill_color = config.plotBackground +# if config.gridColor: +# plot.xgrid.grid_line_color = config.gridColor +# plot.ygrid.grid_line_color = config.gridColor + +# # Colobrewer2 qualitative Set1 (http://colorbrewer2.org) +# colours = [ +# "#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", +# "#a65628", "#f781bf", "#999999" +# ] + +# js_sources = data +# for ct, k in enumerate(line_names): +# k_ = k.replace("-", "_") +# line = plot.line(data_dicts1[k + "_1"]["x"], +# data_dicts1[k + "_1"]["y"], +# color=colours[ct % len(colours)], +# line_width=2, +# legend=k.replace("_", "-")) +# js_sources[k_] = line.data_source + +# code_template = Template(""" +# var seq_num = cb_obj.getv('value'); +# // console.log(seq_num); +# var all_data = { +# {% for trace in trace_names %} +# '{{trace}}': {{trace}}.getv('data'), +# {% endfor %} +# }; +# {% for line in line_names %} +# {{line}}['data'] = {'x': (all_data['{{line}}_'.concat(seq_num.toString())])['x'], +# 'y': (all_data['{{line}}_'.concat(seq_num.toString())])['y']}; +# {% endfor %} +# """) +# rendered = code_template.render( +# line_names=line_names, +# trace_names=list(data.keys())[:-len(line_names)] +# ) + +# callback = CustomJS( +# args=dict(**js_sources), +# code=rendered) + +# if num_seqs > 1: +# slider = Slider(start=1, +# end=num_seqs, +# value=1, +# step=1, +# title="Sequence", +# callback=callback) + +# layout = column(slider, plot) +# show(layout) +# else: +# show(plot) diff --git a/QGL/PulseSequencer.py b/QGL/PulseSequencer.py index be0c6143..e25abac8 100644 --- a/QGL/PulseSequencer.py +++ b/QGL/PulseSequencer.py @@ -33,11 +33,14 @@ class Pulse(namedtuple("Pulse", ["label", "channel", "length", "amp", "phase", "frequency", "frameChange", "shapeParams", "isTimeAmp", "isZero", "ignoredStrParams", - "maddr", "moffset"])): + "maddr", "moffset", "isRunTime"])): __slots__ = () - def __new__(cls, label, channel, shapeParams, amp=1.0, phase=0, frameChange=0, ignoredStrParams=[], maddr=-1, moffset=0): - if hasattr(channel, 'frequency'): + def __new__(cls, label, channel, shapeParams, amp=1.0, phase=0, frameChange=0, + ignoredStrParams=[], maddr=-1, moffset=0, frequency=None, isRunTime=False): + if frequency: + frequency = frequency + elif hasattr(channel, 'frequency'): frequency = channel.frequency else: frequency = 0 @@ -46,12 +49,14 @@ def __new__(cls, label, channel, shapeParams, amp=1.0, phase=0, frameChange=0, i if param not in shapeParams.keys(): raise NameError("shapeParams must include {0}".format(param)) isTimeAmp = (shapeParams['shape_fun'] == PulseShapes.constant) + if isRunTime: + isTimeAmp = False isZero = (amp == 0) return super(cls, Pulse).__new__(cls, label, channel, shapeParams['length'], amp, phase, frequency, frameChange, shapeParams, isTimeAmp, isZero, ignoredStrParams, - maddr, moffset) + maddr, moffset, isRunTime) def __str__(self): kwvals = [] @@ -77,6 +82,12 @@ def _repr_pretty_(self, p, cycle): def hashshape(self): return hash(frozenset(self.shapeParams.items())) + def __hash__(self): + d = self._asdict() + d['shapeParams'] = self.hashshape() + del d['ignoredStrParams'] + return hash(frozenset(d.items())) + def __add__(self, other): if self.channel != other.channel: raise NameError( @@ -107,7 +118,10 @@ def shape(self): params = copy(self.shapeParams) params['sampling_rate'] = self.channel.phys_chan.sampling_rate params.pop('shape_fun') - return self.shapeParams['shape_fun'](**params) + if isinstance(self.shapeParams['shape_fun'],str): + return getattr(PulseShapes, self.shapeParams['shape_fun'])(**params) + else: + return self.shapeParams['shape_fun'](**params) def TAPulse(label, @@ -184,6 +198,10 @@ def frameChange(self): def isZero(self): return all(p.isZero for p in self.pulses) + @property + def isRunTime(self): + return any(hasattr(entry, 'isRunTime') and entry.isRunTime for entry in self.pulses) + class PulseBlock(object): ''' @@ -248,6 +266,11 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + @property + def isRunTime(self): + #Check if any of the member pulses contain a run-time pulse + return any([hasattr(entry, 'isRunTime') and entry.isRunTime for entry in self.pulses.values()]) + @property def channel(self): return self.pulses.keys() @@ -271,7 +294,14 @@ def flatten_to_pulses(obj): for pulse in obj.pulses.values(): yield from flatten_to_pulses(pulse) + def rec_length(obj): + if hasattr(obj, "length"): + return obj.length + else: + return rec_length(obj[0]) + pulse_lengths = np.array([pulse.length for pulse in pulses]) + # pulse_lengths = np.array([rec_length(pulse) for pulse in pulses]) pad_lengths = max(pulse_lengths) - pulse_lengths pulse_list = [] for k,pulse in enumerate(pulses): diff --git a/QGL/PulseShapes.py b/QGL/PulseShapes.py index 2ba601bf..17899d33 100644 --- a/QGL/PulseShapes.py +++ b/QGL/PulseShapes.py @@ -174,7 +174,10 @@ def autodyne(frequency=10e6, baseShape=constant, **params): ''' A pulse with modulation at a particular frequency baked in. ''' - shape = baseShape(**params) + if isinstance(baseShape,str): + shape = globals()[baseShape](**params) + else: + shape = baseShape(**params) # Apply the autodyne frequency timePts = np.linspace(0, params['length'], len(shape)) shape *= np.exp(-1j * 2 * np.pi * frequency * timePts) diff --git a/QGL/RandomCliffordTools.py b/QGL/RandomCliffordTools.py new file mode 100644 index 00000000..1f61c34e --- /dev/null +++ b/QGL/RandomCliffordTools.py @@ -0,0 +1,121 @@ +''' +Functions for dealing with random clifford pulse sequences + +Copyright 2019 Raytheon BBN Technologies + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +''' + +from . import config +from functools import reduce +from . import PatternUtils +from .PatternUtils import flatten, has_gate +from . import Channels +from . import ChannelLibraries +from . import PulseShapes +from . import PulsePrimitives +from . import Compiler +from .PulsePrimitives import Id, clear_pulse_cache +from .PulseSequencer import Pulse, PulseBlock, CompositePulse +from . import ControlFlow +from . import BlockLabel +from . import TdmInstructions # only for APS2-TDM +from .APS2CustomInstructions import * +from .Cliffords import C1, inverse_clifford, clifford_multiply + +default_clifford_options = {"offset": 0x0, "spacing": 0x1, "seed": 0x31} + +VALID_CLIFFORD_TYPES = ('RandomAC', 'RandomCliff', 'RandomTestCliff', 'RandomDiAC') + +def generate_clifford_jump_table(cliff_wires, jt_label = None): + """Generate the jump table that will be used to call into the clifford set""" + + if jt_label is None: + jt_label = BlockLabel.BlockLabel("JT", jump_table=True, table_size=48) + if not isinstance(jt_label, BlockLabel.BlockLabel): + raise ValueError("Jump table label must be a BlockLabel.") + + cliff_labels = [BlockLabel.BlockLabel(f"C{n}") for n in range(24)] + jump_table = [jt_label] + for cl in cliff_labels: + jump_table.append(ControlFlow.Call(cl)) + jump_table.append(ControlFlow.Return()) + + for cliff, cl in zip(cliff_wires, cliff_labels): + cliff.insert(0, cl) + cliff.append(ControlFlow.Return()) + + cliff_wires.insert(0, jump_table) + + return jt_label + +def insert_clifford_calls(seqs, jt_label=None, cliff_addr=0x3, add_inv = True, + inv_addr=0x4, inv_values=[], + clifford_options=default_clifford_options): + + if jt_label is None: + jt_label = BlockLabel.BlockLabel("JT") + if not isinstance(jt_label, BlockLabel.BlockLabel): + raise ValueError("Jump table label must be a BlockLabel.") + + #Insert defaults + for k,v in default_clifford_options.items(): + if k not in clifford_options.keys(): + cliford_options[k] = v + + for idx, seq in enumerate(seqs[:]): + if not PatternUtils.contains_runtime_pulses(seq): + continue + + new_seq = [] + inverse_val = 0 + + for pulse in seq: + if isinstance(pulse, Pulse) and pulse.isRunTime: + if pulse.label in VALID_CLIFFORD_TYPES: + has_random_cliff = True + new_seq.extend(RandomClifford(jt_label, cliff_addr)) + elif pulse.label == 'RandomInverse': + new_seq.extend(RandomCliffordInverse(jt_label, inv_addr)) + elif pulse.label == 'RandomInverseReset': + inverse_val = pulse.maddr + else: + raise Exception(f"Unhandled run-time pulse: {pulse.label}") + #print("Inserting clifford pulse!") + else: + new_seq.append(pulse) + + if add_inv: + w_idx = next(i for i, v in enumerate(new_seq) if isinstance(v, ControlFlow.Wait)) + new_seq.insert(w_idx, RandomCliffordInverseReset(val=inverse_val)) + seqs[idx] = new_seq + + #Helper "sequence" to set the random clifford settings. + info_seqs = [] + info_seqs.extend(RandomCliffordSetOffset(0x1, clifford_options["offset"])) + info_seqs.extend(RandomCliffordSetSpacing(0x2, clifford_options["spacing"])) + info_seqs.extend(RandomCliffordSeed(clifford_options["seed"])) + seqs.insert(0, info_seqs) + + +def randomize_clifford_sequences(qubit, seqs, clifford_type=PulsePrimitives.RandomCliff): + """Randomize a sequence of cliffords (given as integers). + """ + rseqs = [] + for seq in seqs: + inverse = reduce(clifford_multiply, seq) + rseq = ([PulsePrimitives.RandomInverse(qubit, reset_value=inverse)] + + [clifford_type(qubit)]*len(seq) + + [RandomInverse(qubit), MEAS(qubit)]) + rseqs.append(rseq) + return rseqs diff --git a/QGL/TdmInstructions.py b/QGL/TdmInstructions.py index 945743c9..cbb919b5 100644 --- a/QGL/TdmInstructions.py +++ b/QGL/TdmInstructions.py @@ -36,22 +36,32 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + def __str__(self): + return f"{self.instruction}({hex(self.in_addr)}, {hex(self.out_addr)})" + + def __repr__(self): + return self.__str__() + + def MajorityVote(in_addr, out_addr, nmeas): # alternatively, append the loadcmpvram instruction when compiling (see STOREMEAS) return [LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 2**nmeas-1, True), CustomInstruction('MAJORITY', in_addr, out_addr)] def MajorityMask(in_addr, out_addr, value): - return [WriteAddrInstruction('INVALIDATE', None, 1, in_addr, 0x0, True), WriteAddrInstruction('WRITEADDR', None, 0, in_addr, value, True), LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 0xffff, True), CustomInstruction('MAJORITYMASK', in_addr, out_addr)] + return [WriteAddrInstruction('INVALIDATE', None, 1, in_addr, 0x0, True), WriteAddrInstruction('WRITEADDR', None, 0, in_addr, 2**value-1, True), LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 0xffff, True), CustomInstruction('MAJORITYMASK', in_addr, out_addr)] def Decode(in_addr, out_addr, nmeas): return [LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 2**nmeas-1, True), CustomInstruction('TSM', in_addr, out_addr)] def DecodeSetRounds(in_addr, out_addr, value): - return [WriteAddrInstruction('INVALIDATE', None, 1, in_addr, 0x0, True), WriteAddrInstruction('WRITEADDR', None, 0, in_addr, value, True), LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 0xffff, True), CustomInstruction('TSM_SET_ROUNDS', in_addr, out_addr)] + return [WriteAddrInstruction('INVALIDATE', None, 1, in_addr, 0x0, True), WriteAddrInstruction('WRITEADDR', None, 0, in_addr, 2**value-1, True), LoadCmpVramInstruction('LOADCMPVRAM', 1, in_addr, 0xffff, True), CustomInstruction('TSM_SET_ROUNDS', in_addr, out_addr)] # TODO: the rest of the CUSTOM instructions -class WriteAddrInstruction(object): +class VRAMInstruction(object): + pass + +class WriteAddrInstruction(VRAMInstruction): def __init__(self, name, channel, modifier, addr, value, tdm, **kwargs): self.instruction = name @@ -74,6 +84,12 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + def __str__(self): + return f"{self.instruction}({hex(self.addr)}, {hex(self.value)})" + + def __repr__(self): + return self.__str__() + def WriteAddr(addr, value, channel=None, tdm=True): return WriteAddrInstruction('WRITEADDR', channel, 0, addr, value, tdm) @@ -86,7 +102,7 @@ def CrossBar(addr, value, channel=None, tdm=True): # should this be a high-level def StoreMeas(addr, value, channel=None, tdm=True): return WriteAddrInstruction('STOREMEAS', channel, 5, addr, value, tdm) -class LoadCmpVramInstruction(object): +class LoadCmpVramInstruction(VRAMInstruction): def __init__(self, name, use_vram, addr, mask, tdm): # TODO: sanity checks on input values @@ -108,6 +124,12 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + def __str__(self): + return f"{self.instruction}({hex(self.addr)}, {hex(self.mask)})" + + def __repr__(self): + return self.__str__() + -# def LoadCmpVram(addr, mask): -# return LoadCmpVramInstruction('LOADCMPVRAM', 1, addr, mask) +def LoadCmpVram(addr, mask, tdm=True): + return LoadCmpVramInstruction('LOADCMPVRAM', 1, addr, mask, tdm) diff --git a/QGL/__init__.py b/QGL/__init__.py index 2433b99a..82defa84 100644 --- a/QGL/__init__.py +++ b/QGL/__init__.py @@ -1,11 +1,12 @@ -from .Channels import Qubit, Measurement, Edge +from .Channels import Qubit, Measurement, Edge, Generator, ChannelDatabase, Transmitter, Receiver, Transceiver from .ChannelLibraries import QubitFactory, MeasFactory, EdgeFactory, MarkerFactory, ChannelLibrary, channelLib +# from .ChannelLibraries import new_APS2, new_X6, new_APS2_rack, new_Alazar, new_qubit, set_control, set_measure, set_master, new_source from .PulsePrimitives import * from .Compiler import compile_to_hardware, set_log_level from .PulseSequencer import align from .ControlFlow import repeat, repeatall, qif, qwhile, qdowhile, qfunction, qwait, qsync, Barrier from .BasicSequences import * -from .Plotting import output_file, output_notebook, show, build_waveforms, plot_waveforms +from .Plotting import build_waveforms #, show, , plot_waveforms from .PulseSequencePlotter import plot_pulse_files from .Tomography import state_tomo, process_tomo from .Scheduler import schedule diff --git a/QGL/config.py b/QGL/config.py index ef088fd6..e8ae133d 100644 --- a/QGL/config.py +++ b/QGL/config.py @@ -1,18 +1,30 @@ #Package configuration information import os.path +import sys import re -import yaml +import importlib +import tempfile +import logging + +logger = logging.getLogger("QGL") # Where to store AWG data -AWGDir = None +if os.getenv('AWG_DIR'): + AWGDir = os.getenv('AWG_DIR') +else: + logger.warning("AWG_DIR environment variable not defined. Unless otherwise specified, using temporary directory for AWG sequence file outputs.") + AWGDir = tempfile.mkdtemp(prefix="AWG") + +# The db file, where the channel libraries are stored +db_resource_name = None -# The measurement file -meas_file = None +# The config file (executed upon channel library loading) +# config_file = None # plotting options -plotBackground = '#EAEAF2' -gridColor = None +plotBackground = '#EAEAF2' +gridColor = None # select pulse library (standard or all90) pulse_primitives_lib = "standard" @@ -21,77 +33,18 @@ # CNOT in your gate set, e.g. CNOT_simple or CNOT_CR) cnot_implementation = "CNOT_simple" -class LoaderMeta(type): - def __new__(metacls, __name__, __bases__, __dict__): - """Add include constructer to class.""" - # register the include constructor on the class - cls = super().__new__(metacls, __name__, __bases__, __dict__) - cls.add_constructor('!include', cls.construct_include) - return cls -class Loader(yaml.Loader, metaclass=LoaderMeta): - """YAML Loader with `!include` constructor.""" - def __init__(self, stream): - """Initialise Loader.""" - try: - self._root = os.path.split(stream.name)[0] - except AttributeError: - self._root = os.path.curdir - super().__init__(stream) - self.add_implicit_resolver( - u'tag:yaml.org,2002:float', - re.compile(u'''^(?: - [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)? - |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+) - |\\.[0-9_]+(?:[eE][-+][0-9]+)? - |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]* - |[-+]?\\.(?:inf|Inf|INF) - |\\.(?:nan|NaN|NAN))$''', re.X), - list(u'-+0123456789.')) - self.filenames = [os.path.abspath(stream.name)] - def construct_include(self, node): - """Include file referenced at node.""" - filename = os.path.abspath(os.path.join( - self._root, self.construct_scalar(node) - )) - extension = os.path.splitext(filename)[1].lstrip('.') - self.filenames.append(filename) - with open(filename, 'r') as f: - if extension in ('yaml', 'yml'): - return yaml.load(f, Loader) - else: - return ''.join(f.readlines()) - -def find_meas_file(): - if os.getenv('BBN_MEAS_FILE'): - return os.getenv('BBN_MEAS_FILE') - raise Exception("Could not find the measurement file in the environment variables or the auspex globals.") - -def load_config(filename=None): - global meas_file, AWGDir, plotBackground, gridColor, pulse_primitives_lib, cnot_implementation - - if filename: - meas_file = filename - else: - meas_file = find_meas_file() - - with open(meas_file, 'r') as FID: - # cfg = yaml.load(f) - loader = Loader(FID) +def load_config(): + global config_file + if os.getenv('BBN_CONFIG'): try: - cfg = loader.get_single_data() - finally: - loader.dispose() - - # pull out the variables - # abspath allows the use of relative file names in the config file - if 'AWGDir' in cfg['config'].keys(): - AWGDir = os.path.abspath(cfg['config']['AWGDir']) - else: - raise KeyError("Could not find AWGDir in the YAML config section") - - plotBackground = cfg['config'].get('PlotBackground', '#EAEAF2') - gridColor = cfg['config'].get('GridColor', None) - pulse_primitives_lib = cfg['config'].get('PulsePrimitivesLibrary', 'standard') - cnot_implementation = cfg['config'].get('cnot_implementation', 'CNOT_simple') - - return meas_file \ No newline at end of file + config_file = os.getenv("BBN_CONFIG") + sys.path.append(os.path.dirname(config_file)) + importlib.import_module(os.path.splitext(os.path.basename(config_file))[0]) + except: + raise Exception(f"Could not import/execute the BBN_CONFIG {os.getenv('BBN_CONFIG')}") + +def load_db(): + global db_resource_name + if os.getenv('BBN_DB'): + db_resource_name = os.getenv("BBN_DB") + return db_resource_name \ No newline at end of file diff --git a/QGL/config_location.py b/QGL/config_location.py index 16566195..d9304dec 100644 --- a/QGL/config_location.py +++ b/QGL/config_location.py @@ -50,7 +50,7 @@ CONFIG_PATH = None -_CONFIG_FILE_NAME = 'config.json' +_CONFIG_FILE_NAME = 'BBN_config.py' def _set_default_config_path(): """ diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index 224690e3..6ece1645 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -1,5 +1,5 @@ ''' -Module for writing hdf5 APS2 files from sequences and patterns +Module for writing .aps APS2 files from sequences and patterns Copyright 2014 Raytheon BBN Technologies @@ -20,16 +20,19 @@ import logging from warnings import warn from copy import copy -from future.moves.itertools import zip_longest +from itertools import zip_longest import pickle -import h5py +import struct +import sys import numpy as np from QGL import Compiler, ControlFlow, BlockLabel, PatternUtils from QGL import PulseSequencer from QGL.PatternUtils import hash_pulse, flatten from QGL import TdmInstructions +from QGL import APS2CustomInstructions +from QGL.APS2CustomInstructions import APS2_CUSTOM, APS2_CUSTOM_DECODE # Python 2/3 compatibility: use 'int' that subclasses 'long' from builtins import int @@ -85,15 +88,12 @@ CMPTABLE = {'==': EQUAL, '!=': NOTEQUAL, '>': GREATERTHAN, '<': LESSTHAN} -# custom OP_CODES +# custom TDM OP_CODES TDM_MAJORITY_VOTE = 0 TDM_MAJORITY_VOTE_SET_MASK = 1 TDM_TSM_SET_ROUNDS = 2 TDM_TSM = 3 -APS_CUSTOM_DECODE = ["APS_RAND", "APS_CLIFFORD_RAND","APS_CLIFFORD_SET_SEED" ,"APS_CLIFFORD_SET_OFFSET" -, "APS_CLIFFORD_SET_SPACING"] - TDM_CUSTOM_DECODE = ["TDM_MAJORITY_VOTE", "TDM_MAJORITY_VOTE_SET_MASK", "TDM_TSM_SET_ROUNDS", "TDM_TSM"] # Whether we use PHASE_OFFSET modulation commands or bake it into waveform @@ -107,19 +107,15 @@ SEQFILE_PER_CHANNEL = False def get_empty_channel_set(): - return {'ch12': {}, 'ch12m1': {}, 'ch12m2': {}, 'ch12m3': {}, 'ch12m4': {}} - + return {'ch1': {}, 'm1': {}, 'm2': {}, 'm3': {}, 'm4': {}} def get_seq_file_extension(): - return '.h5' - + return '.aps2' def is_compatible_file(filename): - with h5py.File(filename, 'r') as FID: - target = FID['/'].attrs['target hardware'] - if isinstance(target, str): - target = target.encode('utf-8') - if target == b'APS2': + with open(filename, 'rb') as FID: + byte = FID.read(4) + if byte == b'APS2': return True return False @@ -164,7 +160,7 @@ def create_wf_vector(wfLib, seqs): else: #otherwise fill in one cache line at a time - CACHE_LINE_LENGTH = WAVEFORM_CACHE_SIZE / 2 + CACHE_LINE_LENGTH = int(np.round(WAVEFORM_CACHE_SIZE / 2)) - 1 wfVec = np.zeros(CACHE_LINE_LENGTH, dtype=np.int16) offsets = [{}] cache_lines = [] @@ -182,7 +178,7 @@ def create_wf_vector(wfLib, seqs): idx = int(CACHE_LINE_LENGTH * ( (idx + CACHE_LINE_LENGTH) // CACHE_LINE_LENGTH)) wfVec = np.append(wfVec, - np.zeros(CACHE_LINE_LENGTH, + np.zeros(int(CACHE_LINE_LENGTH), dtype=np.int16)) offsets.append({}) @@ -263,9 +259,9 @@ def __str__(self): wfOpCode = (self.payload >> 46) & 0x3 wfOpCodes = ["PLAY", "TRIG", "SYNC", "PREFETCH"] out += wfOpCodes[wfOpCode] - out += "; TA bit={}".format((self.payload >> 45) & 0x1) - out += ", count = {}".format((self.payload >> 24) & 2**21 - 1) - out += ", addr = {}".format(self.payload & 2**24 - 1) + out += "; TA_bit={}".format((self.payload >> 45) & 0x1) + out += ", count={}".format((self.payload >> 24) & 2**21 - 1) + out += ", addr={}".format(self.payload & 2**24 - 1) # # APS3/TDM modifier to use VRAM output # if self.payload & (1 << 48): @@ -276,7 +272,7 @@ def __str__(self): mrkOpCodes = ["PLAY", "TRIG", "SYNC"] out += mrkOpCodes[mrkOpCode] out += "; state={}".format((self.payload >> 32) & 0x1) - out += ", count = {}".format(self.payload & 2**32 - 1) + out += ", count={}".format(self.payload & 2**32 - 1) elif instrOpCode == MODULATION: modulatorOpCode = (self.payload >> 45) & 0x7 @@ -298,21 +294,27 @@ def __str__(self): cmpCodes = ["EQUAL", "NOTEQUAL", "GREATERTHAN", "LESSTHAN"] cmpCode = (self.payload >> 8) & 0x3 out += " | " + cmpCodes[cmpCode] - out += ", value = {}".format(self.payload & 0xff) + out += ", value={}".format(self.payload & 0xff) elif any( [instrOpCode == op for op in [GOTO, CALL, RET, REPEAT, PREFETCH]]): - out += " | target addr = {}".format(self.payload & 2**26 - 1) + if self.use_ram: + out += " RAM" + out += " | target_addr={}".format(self.payload & 2**26 - 1) + elif instrOpCode == LOAD: - out += " | count = {}".format(self.payload) + out += " | count={}".format(self.payload) elif instrOpCode == CUSTOM: store_addr = self.payload & 0xFFFF load_addr = (self.payload >> 16) & 0xFFFF instruction = (self.payload >> 32) & 0xFF - instructionAPS = TDM_CUSTOM_DECODE[instruction] - out += " | instruction = {0} ({1}), load_addr = 0x{2:0x}, store_addr = 0x{3:0x}".format(instruction, instructionAPS, load_addr, store_addr) + if self.decode_as_tdm: + instructionAPS = TDM_CUSTOM_DECODE[instruction] + else: + instructionAPS = APS2_CUSTOM_DECODE[instruction] + out += " | instruction={0} ({1}), load_addr=0x{2:0x}, store_addr=0x{3:0x}".format(instruction, instructionAPS, load_addr, store_addr) elif instrOpCode == WRITEADDR: addr = self.payload & 0xFFFF @@ -338,19 +340,18 @@ def __str__(self): addr = (self.payload >> 16) & 0xFFFF value = (self.payload >> 32) & 0xFFFF - out += "{0} | addr = 0x{1:0x}, {2} = 0x{3:0x}".format(instrStr, addr, valueType, value) + out += "{0} | addr=0x{1:0x}, {2}=0x{3:0x}".format(instrStr, addr, valueType, value) elif instrOpCode == LOADCMP: addr = self.payload & 0xFFFF mask = (self.payload >> 16) & 0xFFFF - use_ram = (self.payload >> 48) & 0x1 - if self.decode_as_tdm and not use_ram: + if self.decode_as_tdm and not self.use_ram: out += "WAITMEAS" else: src = "EXT" - if use_ram: + if self.use_ram: src = "RAM" - out += "LOADCMP | source = {0}, addr = 0x{1:0x}, read_mask = 0x{2:0x}".format(src, addr, mask) + out += "LOADCMP | source={0}, addr=0x{1:0x}, read_mask=0x{2:0x}".format(src, addr, mask) return out def __eq__(self, other): @@ -362,6 +363,9 @@ def __ne__(self, other): def __hash__(self): return hash((self.header, self.payload, self.label)) + def isa(self, value): + return (self.header >> 4) == value + @property def address(self): return self.payload & 0xffffffff # bottom 32-bits of payload @@ -376,7 +380,17 @@ def writeFlag(self): @writeFlag.setter def writeFlag(self, value): - self.header |= value & 0x1 + self.header &= ~(0x1 << 0) #clear bit + self.header |= (value & 0x1) #set bit + + @property + def use_ram(self): + return ((self.payload >> 48) & 0x1) + + @use_ram.setter + def use_ram(self, value): + self.payload &= ~(0x1 << 48) #clear bit + self.payload |= ((value & 0x1) << 48) @property def opcode(self): @@ -449,8 +463,10 @@ def Goto(addr, label=None): return Command(GOTO, addr, label=label) -def Call(addr, label=None): - return Command(CALL, addr, label=label) +def Call(addr, indirect=False, label=None): + cmd = Command(CALL, addr, label=label) + cmd.use_ram = indirect + return cmd def Return(label=None): @@ -515,7 +531,6 @@ def LoadCmpVram(addr, mask, label=None): payload = (1 << 48) | (mask << 16) | addr return Instruction(header, payload, label=label) - def preprocess(seqs, shapeLib): seqs = PatternUtils.convert_lengths_to_samples( seqs, SAMPLING_RATE, ADDRESS_UNIT, Compiler.Waveform) @@ -584,19 +599,13 @@ def to_instruction(self, write_flag=True, label=None): NCO_SELECT_OP_OFFSET = 40 MODULATION_CLOCK = 300e6 - nco_select_bits = {1 : 0b0001, - 2 : 0b0010, - 3 : 0b0100, - 4 : 0b1000, - 15: 0b1111}[self.nco_select] - op_code_map = {"MODULATE": 0x0, "RESET_PHASE": 0x2, "SET_FREQ": 0x6, "SET_PHASE": 0xa, "UPDATE_FRAME": 0xe} payload = (op_code_map[self.instruction] << MODULATOR_OP_OFFSET) | ( - (nco_select_bits) << NCO_SELECT_OP_OFFSET) + (self.nco_select) << NCO_SELECT_OP_OFFSET) if self.instruction == "MODULATE": #zero-indexed quad count payload |= np.uint32(self.length / ADDRESS_UNIT - 1) @@ -624,33 +633,38 @@ def inject_modulation_cmds(seqs): for ct,seq in enumerate(seqs): #check whether we have modulation commands freqs = np.unique([entry.frequency for entry in filter(lambda s: isinstance(s,Compiler.Waveform), seq)]) - if len(freqs) > NUM_NCO: - raise Exception("Max {} frequencies on the same channel allowed.".format(NUM_NCO)) - no_freq_cmds = np.allclose(freqs, 0) + if len(freqs) > 2: + raise Exception("Max {} frequencies on the same channel allowed.".format(2)) + no_freq_cmds = np.all(np.less(np.abs(freqs), 1e-8)) phases = [entry.phase for entry in filter(lambda s: isinstance(s,Compiler.Waveform), seq)] - no_phase_cmds = np.allclose(phases, 0) + no_phase_cmds = np.all(np.less(np.abs(phases), 1e-8)) frame_changes = [entry.frameChange for entry in filter(lambda s: isinstance(s,Compiler.Waveform), seq)] - no_frame_cmds = np.allclose(frame_changes, 0) + no_frame_cmds = np.all(np.less(np.abs(frame_changes), 1e-8)) no_modulation_cmds = no_freq_cmds and no_phase_cmds and no_frame_cmds - if no_modulation_cmds: continue mod_seq = [] pending_frame_update = False + force_phase_update = False + + #check to see if we are in a subroutine by using last instruction as return as a tell + #if so, ensure frame updates do not get dropped + if isinstance(seq[-1], ControlFlow.Return): + force_phase_update = True for entry in seq: #copies to avoid same object having different timestamps later #copy through BlockLabel - if isinstance(entry, BlockLabel.BlockLabel): + if isinstance(entry, BlockLabel.BlockLabel) or isinstance(entry, TdmInstructions.CustomInstruction): mod_seq.append(copy(entry)) #mostly copy through control-flow - elif isinstance(entry, ControlFlow.ControlInstruction) or isinstance(entry, TdmInstructions.LoadCmpVramInstruction) or isinstance(entry, TdmInstructions.WriteAddrInstruction): + elif isinstance(entry, ControlFlow.ControlInstruction) or isinstance(entry, TdmInstructions.VRAMInstruction): #heuristic to insert phase reset before trigger if we have modulation commands if isinstance(entry, ControlFlow.Wait): if not ( no_modulation_cmds and (cur_freq == 0) and (cur_phase == 0)): - mod_seq.append(ModulationCommand("RESET_PHASE", 0xF)) + mod_seq.append(ModulationCommand("RESET_PHASE", 0x3)) for nco_ind, freq in enumerate(freqs): mod_seq.append( ModulationCommand("SET_FREQ", nco_ind + 1, frequency = -freq) ) elif isinstance(entry, ControlFlow.Return): @@ -675,10 +689,11 @@ def inject_modulation_cmds(seqs): mod_seq.append( ModulationCommand("MODULATE", nco_select, length = entry.length)) pending_frame_update = False #now apply non-zero frame changes after so it is applied at end + if entry.frameChange != 0: pending_frame_update = True #zero length frame changes (Z pulses) need to be combined with the previous frame change or injected where possible - if entry.length == 0: + if entry.length == 0 and not force_phase_update: #if the last is a frame change then we can add to the frame change if isinstance(mod_seq[-1], ModulationCommand) and mod_seq[-1].instruction == "UPDATE_FRAME": mod_seq[-1].phase += entry.frameChange @@ -725,7 +740,6 @@ def synchronize_clocks(seqs): syncInstructions = [list(filter( lambda s: isinstance(s, ControlFlow.ControlInstruction), seq)) for seq in seqs if seq] - # Add length to control-flow instructions to make accumulated time match at end of CFI. # Keep running tally of how much each channel has been shifted so far. localShift = [0 for _ in syncInstructions] @@ -805,14 +819,13 @@ def create_seq_instructions(seqs, offsets, label = None): write_flags = [True] * len(entries) for ct, (entry, seq_idx) in enumerate(entries): - #use first non empty sequence for control flow if seq_idx == first_non_empty and ( isinstance(entry, ControlFlow.ControlInstruction) or isinstance(entry, BlockLabel.BlockLabel) or isinstance(entry, TdmInstructions.CustomInstruction) or - isinstance(entry, TdmInstructions.WriteAddrInstruction) or - isinstance(entry, TdmInstructions.LoadCmpVramInstruction)): + #isinstance(entry, TdmInstructions.Instruction) or ?????? + isinstance(entry, TdmInstructions.VRAMInstruction)): if isinstance(entry, BlockLabel.BlockLabel): # carry label forward to next entry label = entry @@ -830,7 +843,7 @@ def create_seq_instructions(seqs, offsets, label = None): elif isinstance(entry, ControlFlow.Goto): instructions.append(Goto(entry.target, label=label)) elif isinstance(entry, ControlFlow.Call): - instructions.append(Call(entry.target, label=label)) + instructions.append(Call(entry.target, indirect = entry.indirect, label=label)) elif isinstance(entry, ControlFlow.Repeat): instructions.append(Repeat(entry.target, label=label)) # value argument commands @@ -845,11 +858,19 @@ def create_seq_instructions(seqs, offsets, label = None): instructions.append(LoadCmpVram(entry.addr, entry.mask, label=label)) # some TDM instructions are ignored by the APS elif isinstance(entry, TdmInstructions.CustomInstruction): - pass + #print(str(entry)) + try: + instructions.append(Custom(entry.in_addr, entry.out_addr, + APS2_CUSTOM[entry.instruction], label=label)) + except KeyError as e: + raise Exception(f"Got unknown APS2 instruction: {e.args[0]} in {str(entry)}.") elif isinstance(entry, TdmInstructions.WriteAddrInstruction): + #print(str(entry)) if entry.instruction == 'INVALIDATE' and entry.tdm == False: instructions.append(Invalidate(entry.addr, entry.value, label=label)) - + if entry.instruction == 'WRITEADDR' and entry.tdm == False: + instructions.append(WriteAddr(entry.addr, entry.value, label=label)) + label=None #Reset label to prevent it propagating in a jump table continue if seq_idx == 0: @@ -929,7 +950,6 @@ def create_instr_data(seqs, offsets, cache_lines): except: pass instructions += seq - #if we have any subroutines then group in cache lines if subroutines_start >= 0: subroutine_instrs = [] @@ -957,12 +977,25 @@ def create_instr_data(seqs, offsets, cache_lines): CACHE_LINE_LENGTH)) #inject prefetch commands before waits wait_idx = [idx for idx, instr in enumerate(instructions) - if (instr.header >> 4) == WAIT] + [len(instructions)] + if instr.isa(WAIT)] + [len(instructions)] instructions_with_prefetch = instructions[:wait_idx[0]] last_prefetch = None + for start, stop in zip(wait_idx[:-1], wait_idx[1:]): call_targets = [instr.target for instr in instructions[start:stop] - if (instr.header >> 4) == CALL] + if instr.isa(CALL)] + + #Check if we call into any jump tables + jump_tables = [label for label in call_targets if label.jump_table] + if len(jump_tables) > 0: + for jt in set(jump_tables): + #Find the start of the jump table + start_idx = next(j for j, instr in enumerate(subroutine_instrs) + if instr.label == jt) + stop_idx = start_idx + jt.table_size + call_targets.extend([instr.target for instr in + subroutine_instrs[start_idx:stop_idx] + if instr.isa(CALL)]) needed_lines = set() for target in call_targets: needed_lines.add(subroutine_cache_line[target]) @@ -979,9 +1012,9 @@ def create_instr_data(seqs, offsets, cache_lines): #pad out instruction vector to ensure circular cache never loads a subroutine pad_instrs = 7 * 128 + (128 - ((len(instructions) + 128) % 128)) instructions += [NoOp()] * pad_instrs - instructions += subroutine_instrs + #turn symbols into integers addresses resolve_symbols(instructions) @@ -993,20 +1026,28 @@ def create_instr_data(seqs, offsets, cache_lines): def resolve_symbols(seq): - symbols = {} - # create symbol look-up table - for ct, entry in enumerate(seq): - if entry.label and entry.label not in symbols: - symbols[entry.label] = ct - # then update - for (ct, entry) in enumerate(seq): - if entry.target: - # find next available label. The TDM may miss some labels if branches only contain waveforms (which are ignored) - for k in range(len(seq)-ct): - temp = seq[ct+k] - if temp.target in symbols: - break - entry.address = symbols[temp.target] + + labeled_entries = [(idx, entry.label) for idx, entry in enumerate(seq) if entry.label is not None] + symbols = {label: idx for idx, label in labeled_entries} + logger.info(f"Found labels: {symbols}") + for entry in seq: + if entry.target is not None and entry.target in symbols.keys(): + entry.address = symbols[entry.target] + + # symbols = {} + # # create symbol look-up table + # for ct, entry in enumerate(seq): + # if entry.label and entry.label not in symbols: + # symbols[entry.label] = ct + # # then update + # for (ct, entry) in enumerate(seq): + # if entry.target: + # # find next available label. The TDM may miss some labels if branches only contain waveforms (which are ignored) + # for k in range(len(seq)-ct): + # temp = seq[ct+k] + # if temp.label in symbols: + # break + # entry.address = symbols[temp.label] def compress_marker(markerLL): @@ -1031,11 +1072,11 @@ def write_sequence_file(awgData, fileName): Main function to pack channel sequences into an APS2 h5 file. ''' # Convert QGL IR into a representation that is closer to the hardware. - awgData['ch12']['linkList'], wfLib = preprocess( - awgData['ch12']['linkList'], awgData['ch12']['wfLib']) + awgData['ch1']['linkList'], wfLib = preprocess( + awgData['ch1']['linkList'], awgData['ch1']['wfLib']) # compress marker data - for field in ['ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']: + for field in ['m1', 'm2', 'm3', 'm4']: if 'linkList' in awgData[field].keys(): PatternUtils.convert_lengths_to_samples(awgData[field]['linkList'], SAMPLING_RATE, 1, @@ -1048,10 +1089,10 @@ def write_sequence_file(awgData, fileName): wfInfo = [] wfInfo.append(create_wf_vector({key: wf.real for key, wf in wfLib.items()}, awgData[ - 'ch12']['linkList'])) + 'ch1']['linkList'])) wfInfo.append(create_wf_vector({key: wf.imag for key, wf in wfLib.items()}, awgData[ - 'ch12']['linkList'])) + 'ch1']['linkList'])) if SAVE_WF_OFFSETS: #create a set of all waveform signatures in offset dictionaries @@ -1062,7 +1103,7 @@ def write_sequence_file(awgData, fileName): wf_sigs |= set(offset_dict.keys()) #create dictionary linking entry labels (that's what we'll have later) with offsets offsets = {} - for seq in awgData['ch12']['linkList']: + for seq in awgData['ch1']['linkList']: for entry in seq: if len(wf_sigs) == 0: break @@ -1086,45 +1127,42 @@ def write_sequence_file(awgData, fileName): # build instruction vector seq_data = [awgData[s]['linkList'] - for s in ['ch12', 'ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']] + for s in ['ch1', 'm1', 'm2', 'm3', 'm4']] instructions = create_instr_data(seq_data, wfInfo[0][1], wfInfo[0][2]) - #Open the HDF5 file + #Open the binary file if os.path.isfile(fileName): os.remove(fileName) - with h5py.File(fileName, 'w') as FID: - FID['/'].attrs['Version'] = 4.0 - FID['/'].attrs['target hardware'] = 'APS2' - FID['/'].attrs['minimum firmware version'] = 4.0 - FID['/'].attrs['channelDataFor'] = np.uint16([1, 2]) + + with open(fileName, 'wb') as FID: + FID.write(b'APS2') # target hardware + FID.write(np.float32(4.0).tobytes()) # Version + FID.write(np.float32(4.0).tobytes()) # minimum firmware version + FID.write(np.uint16(2).tobytes()) # number of channels + # FID.write(np.uint16([1, 2]).tobytes()) # channelDataFor + FID.write(np.uint64(instructions.size).tobytes()) # instructions length + FID.write(instructions.tobytes()) # instructions in uint64 form #Create the groups and datasets for chanct in range(2): - chanStr = '/chan_{0}'.format(chanct + 1) - chanGroup = FID.create_group(chanStr) #Write the waveformLib to file if wfInfo[chanct][0].size == 0: #If there are no waveforms, ensure that there is some element #so that the waveform group gets written to file. #TODO: Fix this in libaps2 - data = np.array([0], dtype=np.uint16) + data = np.array([0], dtype=np.int16) else: data = wfInfo[chanct][0] - FID.create_dataset(chanStr + '/waveforms', data=data) - - #Write the instructions to channel 1 - if np.mod(chanct, 2) == 0: - FID.create_dataset(chanStr + '/instructions', - data=instructions) - + FID.write(np.uint64(data.size).tobytes()) # waveform data length for channel + FID.write(data.tobytes()) def read_sequence_file(fileName): """ - Reads a HDF5 sequence file and returns a dictionary of lists. - Dictionary keys are channel strings such as ch1, ch12m1 + Reads a .aps sequence file and returns a dictionary of lists. + Dictionary keys are channel strings such as ch1, m1 Lists are or tuples of time-amplitude pairs (time, output) """ - chanStrs = ['ch1', 'ch2', 'ch12m1', 'ch12m2', 'ch12m3', 'ch12m4', + chanStrs = ['ch1', 'ch2', 'm1', 'm2', 'm3', 'm4', 'mod_phase'] seqs = {ch: [] for ch in chanStrs} @@ -1137,16 +1175,22 @@ def start_new_seq(): #marker channel seqs[ch].append([]) - with h5py.File(fileName, 'r') as FID: - file_version = FID["/"].attrs["Version"] + with open(fileName, 'rb') as FID: + target_hw = FID.read(4).decode('utf-8') + file_version = struct.unpack('> 2) & 0x3) + 1) + chan = 'm' + str(((instr.header >> 2) & 0x3) + 1) count = instr.payload & 0xffffffff count = (count + 1) * ADDRESS_UNIT state = (instr.payload >> 32) & 0x1 @@ -1452,14 +1496,16 @@ def write_tdm_seq(seq, tdm_fileName): # Utility Functions for displaying programs -def get_channel_instructions_string(channel): - return '/chan_{}/instructions'.format(channel) +def raw_instructions(fileName): + with open(fileName, 'rb') as FID: + target_hw = FID.read(4).decode('utf-8') + file_version = struct.unpack(' 0).tobytes()) # LL for chan1 + FID.write(np.uint8(len(LLData[1]) > 0).tobytes()) # LL for chan3 + for chanct in [0,2]: #For A channels (1 & 3) we write link list data if we actually have any - if (np.mod(chanct, 2) == 0) and LLData[chanct // 2]: - groupStr = chanStr + '/linkListData' - LLGroup = FID.create_group(groupStr) + if LLData[chanct // 2]: LLDataVecs, numEntries = create_LL_data( LLData[chanct // 2], wfInfo[chanct][1], os.path.basename(fileName)) - LLGroup.attrs['length'] = numEntries + FID.write(np.uint64(len(LLDataVecs.keys())).tobytes()) # numKeys + FID.write(np.uint64(numEntries).tobytes()) # numEntries for key, dataVec in LLDataVecs.items(): - FID.create_dataset(groupStr + '/' + key, data=dataVec) - else: - chanGroup.attrs['isLinkListData'] = np.uint8(0) + FID.write(key.ljust(32,"#").encode("utf-8")) # Key 32 byte utf-8 + FID.write(dataVec.tobytes()) # Data np.uint16 def read_sequence_file(fileName): @@ -741,79 +736,99 @@ def read_sequence_file(fileName): chanStrs = ['ch1', 'ch2', 'ch3', 'ch4'] chanStrs2 = ['chan_1', 'chan_2', 'chan_3', 'chan_4'] mrkStrs = ['ch1m1', 'ch2m1', 'ch3m1', 'ch4m1'] - - with h5py.File(fileName, 'r') as FID: - for chanct, chanStr in enumerate(chanStrs2): - #If we're in IQ mode then the Q channel gets its linkListData from the I channel - if FID[chanStr].attrs['isIQMode']: - tmpChan = 2 * (chanct // 2) - curLLData = FID[chanStrs2[tmpChan]][ - 'linkListData'] if "linkListData" in FID[chanStrs2[ - tmpChan]] else [] - else: - curLLData = FID[chanStr][ - 'linkListData'] if "linkListData" in FID[chanStrs2[ - tmpChan]] else [] - - if curLLData: - #Pull out the LL data in sample units - #Cast type to avoid uint16 overflow - addr = (curLLData['addr'].value.astype(np.uint)) * ADDRESS_UNIT - count = ((curLLData['count'].value + 1).astype(np.uint) - ) * ADDRESS_UNIT - repeat = curLLData['repeat'].value - trigger1 = ( - curLLData['trigger1'].value.astype(np.uint)) * ADDRESS_UNIT - trigger2 = ( - curLLData['trigger2'].value.astype(np.uint)) * ADDRESS_UNIT - - #Pull out and scale the waveform data - wf_lib = ( - 1.0 / - MAX_WAVEFORM_VALUE) * FID[chanStr]['waveformLib'].value - - #Initialize the lists of time-amplitude pairs - AWGData[chanStrs[chanct]] = [] - AWGData[mrkStrs[chanct]] = [] - - cum_time = 0 - - #Loop over LL entries - for ct in range(curLLData.attrs['length']): - #If we are starting a new sequence push back an empty array - if START_MINILL_MASK & repeat[ct]: - AWGData[chanStrs[chanct]].append([]) - trigger_delays = [0] - cum_time = 0 - - #Record the trigger delays - if np.mod(chanct, 2) == 0: - if trigger1[ct] > 0: - trigger_delays.append(cum_time + trigger1[ct]) - else: - if trigger2[ct] > 0: - trigger_delays.append(cum_time + trigger2[ct]) - - #waveforms - wf_repeat = (repeat[ct] & REPEAT_MASK) + 1 - if TA_PAIR_MASK & repeat[ct]: - AWGData[chanStrs[chanct]][-1].append( - (wf_repeat * count[ct], wf_lib[addr[ct]])) - else: - for repct in range(wf_repeat): - for sample in wf_lib[addr[ct]:addr[ct] + count[ - ct]]: - AWGData[chanStrs[chanct]][-1].append( - (1, sample)) - - cum_time += count[ct] - - #Create the trigger sequence - if END_MINILL_MASK & repeat[ct]: - AWGData[mrkStrs[chanct]].append([]) - for delay in np.diff(trigger_delays): - AWGData[mrkStrs[chanct]][-1].append((delay - 1, 0)) - AWGData[mrkStrs[chanct]][-1].append((1, 1)) + + data = {} + with open(fileName, 'rb') as FID: + target_hw = FID.read(4).decode('utf-8') + file_version = struct.unpack(' 0: + trigger_delays.append(cum_time + trigger1[ct]) + else: + if trigger2[ct] > 0: + trigger_delays.append(cum_time + trigger2[ct]) + + #waveforms + wf_repeat = (repeat[ct] & REPEAT_MASK) + 1 + if TA_PAIR_MASK & repeat[ct]: + AWGData[chanStrs[chanct]][-1].append( + (wf_repeat * count[ct], wf_lib[addr[ct]])) + else: + for repct in range(wf_repeat): + for sample in wf_lib[addr[ct]:addr[ct] + count[ + ct]]: + AWGData[chanStrs[chanct]][-1].append( + (1, sample)) + + cum_time += count[ct] + + #Create the trigger sequence + if END_MINILL_MASK & repeat[ct]: + AWGData[mrkStrs[chanct]].append([]) + for delay in np.diff(trigger_delays): + AWGData[mrkStrs[chanct]][-1].append((delay - 1, 0)) + AWGData[mrkStrs[chanct]][-1].append((1, 1)) return AWGData diff --git a/QGL/drivers/TekPattern.py b/QGL/drivers/TekPattern.py deleted file mode 100644 index 11464977..00000000 --- a/QGL/drivers/TekPattern.py +++ /dev/null @@ -1,405 +0,0 @@ -""" -TekPattern for creating Tek AWG files. Based off of the Matlab version. - -Created on Tue May 8 20:39:26 2012 - -Copyright 2013 Raytheon BBN Technologies - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import struct -import io -import h5py -import numpy as np -import re - -MAX_WAVEFORM_VALUE = 2**13 - 1 #maximum waveform value i.e. 14bit DAC - -# Do we want a pulse file per instrument or per channel -SEQFILE_PER_CHANNEL = False - -def get_empty_channel_set(): - return {'ch12': {}, - 'ch34': {}, - 'ch1m1': {}, - 'ch1m2': {}, - 'ch2m1': {}, - 'ch2m2': {}, - 'ch3m1': {}, - 'ch3m2': {}, - 'ch4m1': {}, - 'ch4m2': {}} - - -def get_seq_file_extension(): - return '.awg' - - -def is_compatible_file(filename): - import os - if os.path.splitext(filename)[1] == get_seq_file_extension(): - return True - else: - return False - - -def write_field(FID, fieldName, data, dataType): - typeSizes = {'int16': 2, 'int32': 4, 'double': 8, 'uint128': 16} - formatChars = {'int16': ' 1] = 1.0 - analog[analog < -1] = -1.0 - - maxLength = max(analog.size, marker1.size, marker2.size) - - if marker1.size < maxLength: - marker1 = np.append(marker1, - np.zeros(maxLength - marker1.size, - dtype=np.bool)) - if marker2.size < maxLength: - marker2 = np.append(marker2, - np.zeros(maxLength - marker2.size, - dtype=np.bool)) - if analog.size < maxLength: - analog = np.append(analog, - np.zeros(maxLength - analog.size, - dtype=np.float64)) - - binData = np.uint16(MAX_WAVEFORM_VALUE * analog + MAX_WAVEFORM_VALUE) - binData += 2**14 * np.uint16(marker1) + 2**15 * np.uint16(marker2) - - return binData - - -def write_waveform(FID, WFname, WFnumber, data): - ''' - Helper function to write a waveform - ''' - numString = str(WFnumber) - - write_field(FID, 'WAVEFORM_NAME_' + numString, WFname, 'char') - - #Set integer format - write_field(FID, 'WAVEFORM_TYPE_' + numString, 1, 'int16') - - write_field(FID, 'WAVEFORM_LENGTH_' + numString, data.size, 'int32') - - write_field(FID, 'WAVEFORM_TIMESTAMP_' + numString, 0, 'uint128') - tmpString = 'WAVEFORM_DATA_' + numString + chr(0) - dataSize = 2 * data.size - FID.write(struct.pack('> 14 - wfData[name + 'm2'] = (wf & marker2Mask) >> 15 - elif nameRE.match(name): - wfNum = nameRE.findall(name)[0] - waveformNames[data] = 'WAVEFORM_DATA_' + wfNum - elif seqNameRE.match(name): - channel, seqNum = seqNameRE.findall(name)[0] - if not ('ch' + channel) in seqTable: - seqTable['ch' + channel] = {int(seqNum): data} - else: - seqTable['ch' + channel][int(seqNum)] = data - - # check if there is more to read - b = FID.read(1) - if b == '': - break - else: - FID.seek(-1, 1) - - # now that we have everything, loop through seqTable to build AWGData - AWGData = {ch: [] for ch in seqTable.keys()} - # add in marker keys - for ch in seqTable.keys(): - AWGData[ch + 'm1'] = [] - AWGData[ch + 'm2'] = [] - - seqLength = max([int(x) for x in seqTable['ch1'].keys()]) - - for channel in seqTable.keys(): - for seqct in range(seqLength): - seqEntry = seqTable[channel][seqct + 1] - wfName = waveformNames[seqEntry] - AWGData[channel].append(wfData[wfName]) - AWGData[channel + 'm1'].append(wfData[wfName + 'm1']) - AWGData[channel + 'm2'].append(wfData[wfName + 'm2']) - - return AWGData - - -if __name__ == '__main__': - - pass diff --git a/.gitmodules b/QGL/test_helpers.py similarity index 100% rename from .gitmodules rename to QGL/test_helpers.py diff --git a/README.md b/README.md index 57b51930..545757d1 100644 --- a/README.md +++ b/README.md @@ -50,20 +50,14 @@ going to System -> Advanced Settings -> Environment variables. On Mac/Linux machines add the following line to your .bashrc or .bash_profile: ``` export PYTHONPATH=/path/to/QGL/repo:$PYTHONPATH``` + The QGL config file will be created the first time you run `import QGL` or `from QGL import *`. ## Dependencies * Python 2.7 or 3.4+ -* JSONLibraryUtils (https://github.com/BBN-Q/JSONLibraryUtils, integrated as a Git submodule) * Numpy/Scipy -* Nucleic atom (from ecpy channel for Python 3) * h5py -* watchdog * Bokeh 0.11 * networkx 2.0 * iPython/Jupyter 4.0 (only for Jupyter notebooks) -* ruamel_yaml - -## UnitTest data support -This repository uses the Git Large File Storage (LFS) extension to manage a few -UnitTest data files (see https://git-lfs.github.com/). +* bbndb diff --git a/doc/config/filters.yml b/doc/config/filters.yml deleted file mode 100644 index 546d978d..00000000 --- a/doc/config/filters.yml +++ /dev/null @@ -1,4 +0,0 @@ -q1-RawSS: - type: X6StreamSelector - source: X6-1 - channel: '1' diff --git a/doc/config/instruments.yml b/doc/config/instruments.yml deleted file mode 100644 index 14fd6b6f..00000000 --- a/doc/config/instruments.yml +++ /dev/null @@ -1,18 +0,0 @@ -BBNAPS1: - type: APS2 - tx_channels: - '12': - markers: - 12m1: - delay: -5.0e-08 - -BBNAPS2: - type: APS2 - tx_channels: - '12': - -X6-1: - type: X6 - rx_channels: - '1': - '2': diff --git a/doc/config/measure.yml b/doc/config/measure.yml deleted file mode 100644 index 58327b57..00000000 --- a/doc/config/measure.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Minimal QGL configuration for QGL-demo notebook -# Imports can be made using the !include keyword. e.g. -# instruments: !include instruments.yml -config: - AWGDir: "./awg/" -qubits: - q1: - measure: - AWG: BBNAPS1 12 - trigger: BBNAPS1 12m1 - receiver: q1-RawSS - control: - AWG: BBNAPS2 12 - -instruments: !include instruments.yml -filters: !include filters.yml diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..31600f5c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +bbndb >= 0.1 +numpy >= 1.11.1 +scipy >= 0.17.1 +networkx >= 1.11 +bqplot >= 0.11.5 +sqlalchemy >= 1.2.15 \ No newline at end of file diff --git a/setup.py b/setup.py index dee9e96b..07db1d0b 100644 --- a/setup.py +++ b/setup.py @@ -5,16 +5,10 @@ url='https://github.com/BBN-Q/QGL', packages=find_packages(exclude=["tests"]), install_requires=[ - "numpy >= 1.11.1", - "scipy >= 0.17.1", - "jupyter >= 1.0.0", - "atom >= 0.4.1", - "h5py >= 2.6.0", - "networkx >= 2.0", - "future >= 0.16", - "watchdog >= 0.8.3", - "bokeh >= 0.11", - "ruamel_yaml >= 0.11.14" - ], - extras_require={"gst": "pygsti>0.9.4"} -) + "bbndb >= 0.1", + "numpy >= 1.11.1", + "scipy >= 0.17.1", + "networkx >= 1.11", + "bqplot >= 0.11.5", + "sqlalchemy >= 1.2.15" + ]) diff --git a/tests/compare_test_data.py b/tests/compare_test_data.py index 34f7daa8..3a49a58c 100644 --- a/tests/compare_test_data.py +++ b/tests/compare_test_data.py @@ -1,7 +1,6 @@ import os import sys import glob -import h5py from builtins import input from QGL import * @@ -18,17 +17,14 @@ def compare_sequences(seq_filter=""): for test in testdirs: # build up subdirectory name _, name = os.path.split(test) - testfiles = glob.glob(os.path.join(test, '*.h5')) + testfiles = glob.glob(os.path.join(test, '*.aps*')) # recurse into subdirectories while len(testfiles) == 1 and os.path.isdir(testfiles[0]): _, subname = os.path.split(testfiles[0]) name = os.path.join(name, subname) testfiles = glob.glob(os.path.join(testfiles[0], '*')) newpath = os.path.join(BASE_AWG_DIR, subdir, name) - newfiles = glob.glob(os.path.join(newpath, '*.h5')) - #filter py27 look for py27 versions - testfiles = filter_py27(testfiles) - newfiles = filter_py27(newfiles) + newfiles = glob.glob(os.path.join(newpath, '*.aps*')) if seq_filter and any(seq_filter in seq_file for seq_file in testfiles): print("{0} comparing to {1}".format(test, newpath)) PulseSequencePlotter.plot_pulse_files_compare(testfiles, newfiles) @@ -36,32 +32,19 @@ def compare_sequences(seq_filter=""): if c == 'q': break - -def filter_py27(filenames): - py27_files = [f for f in filenames if f[-8:] == "_py27.h5"] - if py27_files: - if sys.version_info[0] > 2: - #strip them out for python3 (and above?) - filenames = [f for f in filenames if f[-8:] != "_py27.h5"] - else: - #otherwise strip the non "_py27" version - filenames = [f for f in filenames - if f.replace(".h5", "_py27.h5") not in py27_files] - return filenames - - def update_test_files(): - for device in ['APS1', 'APS2']: - testdirs = glob.glob(os.path.join(BASE_TEST_DIR, 'Test' + device, '*')) - for test in testdirs: - testfiles = glob.glob(os.path.join(test, '*')) - # recurse into subdirectories - while len(testfiles) == 1 and os.path.isdir(testfiles[0]): - testfiles = glob.glob(os.path.join(testfiles[0], '*')) - for tfile in testfiles: - FID = h5py.File(tfile) - FID['/'].attrs['target hardware'] = device - FID.close() + raise Exception("update_test_files must be updated for new binary format") + # for device in ['APS1', 'APS2']: + # testdirs = glob.glob(os.path.join(BASE_TEST_DIR, 'Test' + device, '*')) + # for test in testdirs: + # testfiles = glob.glob(os.path.join(test, '*')) + # # recurse into subdirectories + # while len(testfiles) == 1 and os.path.isdir(testfiles[0]): + # testfiles = glob.glob(os.path.join(testfiles[0], '*')) + # for tfile in testfiles: + # FID = h5py.File(tfile) + # FID['/'].attrs['target hardware'] = device + # FID.close() if __name__ == '__main__': diff --git a/tests/helpers.py b/tests/helpers.py index 97f3e7f8..1f663643 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,20 +1,24 @@ from QGL import * def setup_test_lib(): - ChannelLibrary(blank=True) - - q1 = Qubit(label='q1') - q2 = Qubit(label='q2') - q3 = Qubit(label='q3') - q4 = Qubit(label='q4') + cl = ChannelLibrary(db_resource_name=":memory:") + cl.clear() + q1 = cl.new_qubit(label='q1') + q2 = cl.new_qubit(label='q2') + q3 = cl.new_qubit(label='q3') + q4 = cl.new_qubit(label='q4') + m1 = Measurement(label='M-q1', control_chan=q1, channel_db=cl.channelDatabase) + m2 = Measurement(label='M-q2', control_chan=q2, channel_db=cl.channelDatabase) + m3 = Measurement(label='M-q3', control_chan=q3, channel_db=cl.channelDatabase) + m4 = Measurement(label='M-q4', control_chan=q4, channel_db=cl.channelDatabase) ChannelLibraries.channelLib.channelDict = { 'q1': q1, 'q2': q2, 'q3': q3, 'q4': q4, - 'q1q2': Edge(label='q1q2', source=q1, target=q2), - 'q2q3': Edge(label='q2q3', source=q2, target=q3), - 'q3q4': Edge(label='q3q4', source=q3, target=q4) + 'q1q2': Edge(label='q1q2', source=q1, target=q2, channel_db=cl.channelDatabase), + 'q2q3': Edge(label='q2q3', source=q2, target=q3, channel_db=cl.channelDatabase), + 'q3q4': Edge(label='q3q4', source=q3, target=q4, channel_db=cl.channelDatabase) } - ChannelLibraries.channelLib.build_connectivity_graph() + cl.update_channelDict() diff --git a/tests/test_APS2Pattern.py b/tests/test_APS2Pattern.py index 636d7843..08874cea 100644 --- a/tests/test_APS2Pattern.py +++ b/tests/test_APS2Pattern.py @@ -1,4 +1,3 @@ -import h5py import unittest import numpy as np from copy import copy @@ -9,15 +8,12 @@ class APSPatternUtils(unittest.TestCase): def setUp(self): - self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate') - self.q1 = Qubit(label='q1', gate_chan=self.q1gate) - self.q1 = Qubit(label='q1') + self.cl = ChannelLibrary(db_resource_name=":memory:") + self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate', channel_db=self.cl.channelDatabase) + self.q1 = self.cl.new_qubit(label='q1') + self.q1.gate_chan = self.q1gate self.q1.pulse_params['length'] = 30e-9 - - ChannelLibrary(blank=True) # Create a blank ChannelLibrary - ChannelLibraries.channelLib.channelDict = {'q1': self.q1, - 'q1-gate': self.q1gate} - ChannelLibraries.channelLib.build_connectivity_graph() + self.cl.update_channelDict() def test_synchronize_control_flow(self): q1 = self.q1 diff --git a/tests/test_APSPattern.py b/tests/test_APSPattern.py index 163f3d21..f2e8d3e5 100644 --- a/tests/test_APSPattern.py +++ b/tests/test_APSPattern.py @@ -1,4 +1,3 @@ -import h5py import unittest import numpy as np @@ -8,14 +7,12 @@ class APSPatternUtils(unittest.TestCase): def setUp(self): - # self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate') - # self.q1 = Qubit(label='q1', gate_chan=self.q1gate) - self.q1 = Qubit(label='q1') + self.cl = ChannelLibrary(db_resource_name=":memory:") + self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate', channel_db=self.cl.channelDatabase) + self.q1 = self.cl.new_qubit(label='q1') + self.q1.gate_chan = self.q1gate self.q1.pulse_params['length'] = 30e-9 - - ChannelLibrary(blank=True) # Create a blank ChannelLibrary - ChannelLibraries.channelLib.channelDict = {'q1': self.q1} - ChannelLibraries.channelLib.build_connectivity_graph() + self.cl.update_channelDict() def test_unroll_loops_simple(self): q1 = self.q1 diff --git a/tests/test_Compiler.py b/tests/test_Compiler.py index 8c1bd9c7..0482b3e2 100644 --- a/tests/test_Compiler.py +++ b/tests/test_Compiler.py @@ -1,4 +1,3 @@ -import h5py import unittest import numpy as np @@ -7,23 +6,28 @@ class CompileUtils(unittest.TestCase): def setUp(self): - self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate') - self.q1 = Qubit(label='q1', gate_chan=self.q1gate) + print("Running setup") + self.cl = ChannelLibrary(db_resource_name=":memory:") + self.cl.clear() + self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate', channel_db=self.cl.channelDatabase) + self.q1gate = Channels.LogicalMarkerChannel(label='q1-gate', channel_db=self.cl.channelDatabase) + self.q1phys = Channels.PhysicalChannel(label='q1-phys', sampling_rate=1.2e9, channel_db=self.cl.channelDatabase) + self.q1 = Qubit(label='q1', gate_chan=self.q1gate, channel_db=self.cl.channelDatabase) + self.q1.phys_chan = self.q1phys self.q1.pulse_params['length'] = 30e-9 - self.q2gate = Channels.LogicalMarkerChannel(label='q2-gate') - self.q2 = Qubit(label='q2', gate_chan=self.q2gate) + self.q2gate = Channels.LogicalMarkerChannel(label='q2-gate', channel_db=self.cl.channelDatabase) + self.q2phys = Channels.PhysicalChannel(label='q2-phys', sampling_rate=1.2e9, channel_db=self.cl.channelDatabase) + self.q2 = Qubit(label='q2', gate_chan=self.q2gate, channel_db=self.cl.channelDatabase) + self.q2.phys_chan = self.q2phys self.q2.pulse_params['length'] = 30e-9 - self.trigger = Channels.LogicalMarkerChannel(label='trigger') - self.measq1 = Channels.Measurement(label='M-q1', meas_type='autodyne') + self.trigger = Channels.LogicalMarkerChannel(label='trigger', channel_db=self.cl.channelDatabase) + self.measq1 = Channels.Measurement(label='M-q1', meas_type='autodyne', channel_db=self.cl.channelDatabase) self.measq1.trig_chan = self.trigger - - ChannelLibrary(blank=True) # Create a blank ChannelLibrary - ChannelLibraries.channelLib.channelDict = {'q1': self.q1, - 'q2': self.q2, - 'M-q1': self.measq1} - ChannelLibraries.channelLib.build_connectivity_graph() + self.measq2 = Channels.Measurement(label='M-q2', meas_type='autodyne', channel_db=self.cl.channelDatabase) + self.measq2.trig_chan = self.trigger + self.cl.update_channelDict() def test_add_digitizer_trigger(self): q1 = self.q1 diff --git a/tests/test_ControlFlow.py b/tests/test_ControlFlow.py index 5e430427..f9bbaf41 100644 --- a/tests/test_ControlFlow.py +++ b/tests/test_ControlFlow.py @@ -7,12 +7,12 @@ class ControlFlowTest(unittest.TestCase): def setUp(self): - self.q1 = Qubit(label='q1') - self.q2 = Qubit(label='q2') - - ChannelLibrary(blank=True) # Create a blank ChannelLibrary - ChannelLibraries.channelLib.channelDict = {'q1': self.q1, 'q2': self.q2} - ChannelLibraries.channelLib.build_connectivity_graph() + cl = ChannelLibrary(db_resource_name=":memory:") + self.q1 = cl.new_qubit(label='q1') + self.q2 = cl.new_qubit(label='q2') + self.q3 = cl.new_qubit(label='q3') + self.q4 = cl.new_qubit(label='q4') + cl.update_channelDict() def test_qif(self): q1 = self.q1 @@ -20,8 +20,6 @@ def test_qif(self): seq2 = [X(q1), Y(q1), Z(q1)] label(seq1) label(seq2) - # print qif(0, seq1, seq2) - # print ([CmpEq(0), Goto(label(seq1))] + seq2 + [Goto(endlabel(seq1))] + seq1 assert (qif(0, seq1, seq2) == [CmpEq("m", 0), Goto(label(seq1))] + seq2 + [Goto(endlabel(seq1))] + seq1) diff --git a/tests/test_QGL.py b/tests/test_QGL.py index b91156b0..6255d509 100644 --- a/tests/test_QGL.py +++ b/tests/test_QGL.py @@ -1,9 +1,9 @@ -import h5py import unittest import numpy as np import time import os.path - +import struct +from bbndb.qgl import PhysicalChannel, LogicalChannel, Measurement from QGL import * # Waveform numpy assert_allclose Test for QGL @@ -33,7 +33,7 @@ def __init__(self): # all available sequences (which are defined in subclasses) self.generate() self.compile() - self.load() + self.load() def generate(self): # this function should be overridden in a subclass to define @@ -55,28 +55,29 @@ def show(self): def build_filename(self, name): # utility for reading and writing - return self.testFileDirectory + self.fileHeader + '-' + name + '.h5' + return self.testFileDirectory + self.fileHeader + '-' + name + '.aps2' def write(self): # writes each sequence to a file in the test data directory a file header # which may be overridden in the subclasses for name, waveform in self.waveforms.items(): + fileName = self.build_filename(name) - #Open the HDF5 file if os.path.isfile(fileName): os.remove(fileName) - with h5py.File(fileName, 'w') as FID: - FID['/'].attrs['Type'] = 'test_case' - FID['/'].attrs['Version'] = 1.0 + with open(fileName, 'wb') as FID: + FID.write(b'TEST') # target + FID.write(np.float32(1.0).tobytes()) # Version + FID.write(np.float32(1.0).tobytes()) # minimum firmware version + FID.write(np.uint16(len(waveform)).tobytes()) # number of channels - #Create the groups and datasets channels = waveform.keys() - chanStr = '/channels' - chanGroup = FID.create_group(chanStr) for channel in channels: - channelStr = channel.label - FID.create_dataset('/' + chanStr + '/' + channelStr, - data=waveform[channel]) + channel.label.ljust(32,"#").encode("utf-8") + FID.write(channel.label.ljust(32,"#").encode("utf-8")) + FID.write(np.uint64(waveform[channel].size).tobytes()) + FID.write(np.complex128(waveform[channel]).tobytes()) # waveform data length for channel + def load(self): # attempts to load valid waveforms for each of the sequences test cases @@ -89,22 +90,30 @@ def load(self): caseName, fileName)) continue # ----- - # print( "\n\rDBG::Calling \"with h5py.File( {0}, 'r')\"...".format( fileName) ) + # print( "\n\rDBG::Calling \"with open({0}, 'wb')\"...".format( fileName) ) # ----- # The following pulls in Git Large File Storage (LFS) data files - # from cached signature references; if the h5py.File call fails + # from cached signature references; if the open call fails # with an OSError, double-check git-lfs library installation (in # addition to git) -- # - # Where git-lfs was NOT installed the h5py.File() call was observed + # Where git-lfs was NOT installed the open call was observed # returning: # # OSError: Unable to open file (file signature not found)) # - with h5py.File(fileName, 'r') as FID: - # print( "DBG::FID: {0}".format( FID)) - for name, waveform in FID['/channels'].items(): - validWaveform[name] = waveform[:] + with open(fileName, 'rb') as FID: + target_hw = FID.read(4).decode('utf-8') + file_version = struct.unpack(' 2: - #strip them out for python3 (and above?) - filenames = [f for f in filenames if f[-8:] != "_py27.h5"] - else: - #otherwise strip the non "_py27" version - filenames = [f for f in filenames - if f.replace(".h5", "_py27.h5") not in py27_files] - for filename in filenames: truthFile = os.path.join(truthDirectory, filename) - testFile = os.path.join(searchDirectory, filename.replace("_py27", - "")) + testFile = os.path.join(searchDirectory, filename) self.assertTrue( os.path.isfile(truthFile), @@ -179,7 +176,6 @@ def compare_sequence(self, seqA, seqB, errorHeader): for ta in seqA]) if len(seqA) else np.empty(0) wfB = np.concatenate([ta[1] * np.ones(int(ta[0])) for ta in seqB]) if len(seqB) else np.empty(0) - self.assertTrue( len(wfA) == len(wfB), "{} size {} != size {}".format( errorHeader, len(wfA), len(wfB))) @@ -384,40 +380,108 @@ def test_RB_SimultaneousRB_AC(self): SimultaneousRB_AC((self.q1, self.q2), (seqs1, seqs2)) self.compare_sequences('RB') + @unittest.skip("Need to update to new pygsti API") + def test_1Q_GST(self): + + if istravis: + raise unittest.SkipTest("FIX ME -- Figure out pygsti integration for Travis.") + + self.set_awg_dir('GST') + # list of GST gate strings + if GSTTools.PYGSTI_PRESENT: + # generate the gate gatestrings + import pygsti + from pygsti.construction import std1Q_XYI + + #Create a data set + gs_target = std1Q_XYI.gs_target + fiducials = std1Q_XYI.fiducials + germs = std1Q_XYI.germs + maxLengths = [1,2,4] + + listOfExperiments = pygsti.construction.make_lsgst_experiment_list(gs_target.gates.keys(), fiducials, fiducials, germs, maxLengths) + else: + listOfExperiments = list(np.load('tests/test_data/awg/TestAPS2/GST/GST/listOfExperiments.npy')) + + seqs = list(GSTTools.gst_map_1Q(listOfExperiments, self.q1)) + filenames = compile_to_hardware(seqs, 'GST/GST') + self.compare_sequences('GST') + + @unittest.skip("Need to update to new pygsti API") + def test_2Q_GST(self): + + if istravis: + raise unittest.SkipTest("FIX ME -- Figure out pygsti integration for Travis.") + + self.set_awg_dir('GST') + def gst_2Qgate_map(q1, q2): + return {"Gxi": X90(q1)*Id(q2), + "Gyi": Y90(q1)*Id(q2), + "Gii": Id(q1)*Id(q2), + "Gix": Id(q1)*X90(q2), + "Giy": Id(q1)*Y90(q2), + "Gcnot": CNOT_CR(q2,q1)} + + if GSTTools.PYGSTI_PRESENT: + import pygsti + from pygsti.construction import std1Q_XYI, std2Q_XYICNOT + from itertools import product + from QGL.GSTTools import SingleQubitCliffordGST, gst_map_2Q + # note the use of the germs_lite! + gs = std2Q_XYICNOT + gs_target = std2Q_XYICNOT.gs_target.copy() + + prep_fiducials = std2Q_XYICNOT.prepStrs + effect_fiducials = std2Q_XYICNOT.effectStrs + gs_germs = std2Q_XYICNOT.germs_lite + #maxLengths = [1,2,4,8,16] + maxLengths = [1,2] + + print('Creating GST sequences...') + listOfExperiments = pygsti.construction.make_lsgst_experiment_list(gs_target.gates.keys(), prep_fiducials, effect_fiducials, gs_germs, maxLengths) + else: + # list of GST gate strings + listOfExperiments = list(np.load('tests/test_data/awg/TestAPS2/GST/GST2Q/listOfExperiments.npy')) + + seqs = list(GSTTools.gst_map_2Q(listOfExperiments, (self.q1, self.q2), qgl_map = gst_2Qgate_map(self.q1, self.q2), append_meas=True)) + + filenames = compile_to_hardware(seqs, 'GST/GST2Q') + self.compare_sequences('GST2Q') + class APS2Helper(AWGTestHelper): def setUp(self): AWGTestHelper.__init__(self, APS2Pattern) for name in ['APS1', 'APS2', 'APS3', 'APS4', 'APS5', 'APS6']: - channelName = name + '-12' - channel = PhysicalQuadratureChannel(label=channelName) + channelName = name + '-1' + channel = PhysicalQuadratureChannel(label=channelName, channel=0) channel.sampling_rate = 1.2e9 channel.instrument = name channel.translator = 'APS2Pattern' self.channels[channelName] = channel for m in range(1, 5): - channelName = "{0}-12m{1}".format(name, m) - channel = PhysicalMarkerChannel(label=channelName) + channelName = "{0}-m{1}".format(name, m) + channel = PhysicalMarkerChannel(label=channelName, channel=m-1) channel.sampling_rate = 1.2e9 channel.instrument = name channel.translator = 'APS2Pattern' self.channels[channelName] = channel - mapping = {'digitizerTrig': 'APS1-12m1', - 'slave_trig': 'APS1-12m2', - 'q1': 'APS1-12', - 'q1-gate': 'APS1-12m3', - 'M-q1': 'APS2-12', - 'M-q1-gate': 'APS2-12m1', - 'q2': 'APS3-12', - 'q2-gate': 'APS3-12m1', - 'M-q2': 'APS4-12', - 'M-q2-gate': 'APS4-12m1', - 'cr': 'APS5-12', - 'cr-gate': 'APS5-12m1', - 'M-q1q2': 'APS6-12', - 'M-q1q2-gate': 'APS6-12m1'} + mapping = {'digitizerTrig': 'APS1-m1', + 'slave_trig': 'APS1-m2', + 'q1': 'APS1-1', + 'q1-gate': 'APS1-m3', + 'M-q1': 'APS2-1', + 'M-q1-gate': 'APS2-m1', + 'q2': 'APS3-1', + 'q2-gate': 'APS3-m1', + 'M-q2': 'APS4-1', + 'M-q2-gate': 'APS4-m1', + 'cr': 'APS5-1', + 'cr-gate': 'APS5-m1', + 'M-q1q2': 'APS6-1', + 'M-q1q2-gate': 'APS6-m1'} self.finalize_map(mapping) @@ -434,7 +498,7 @@ def test_mux_CR(self): self.channels['cr'].phys_chan = self.channels['q1'].phys_chan self.channels['q1'].frequency = 100e6 self.channels['cr'].frequency = 200e6 - ChannelLibraries.channelLib.build_connectivity_graph() + self.cl.update_channelDict() seqs = [[CNOT_CR(self.q1, self.q2)]] filenames = compile_to_hardware(seqs, 'CNOT_CR_mux/CNOT_CR_mux') @@ -445,9 +509,9 @@ class TestAPS1(unittest.TestCase, AWGTestHelper, TestSequences): def setUp(self): AWGTestHelper.__init__(self, APSPattern) for name in ['APS1', 'APS2', 'APS3']: - for ch in ['12', '34']: + for i, ch in enumerate(['12', '34']): channelName = name + '-' + ch - channel = PhysicalQuadratureChannel(label=channelName) + channel = PhysicalQuadratureChannel(label=channelName, channel=i) channel.sampling_rate = 1.2e9 channel.instrument = name channel.translator = 'APSPattern' @@ -455,7 +519,7 @@ def setUp(self): for m in range(1, 5): channelName = "{0}-{1}m1".format(name, m) - channel = PhysicalMarkerChannel(label=channelName) + channel = PhysicalMarkerChannel(label=channelName, channel=m-1) channel.sampling_rate = 1.2e9 channel.instrument = name channel.translator = 'APSPattern' @@ -552,186 +616,5 @@ def test_RB_SimultaneousRB_AC(self): """ TestSequences.test_RB_SimultaneousRB_AC(self) - -class TestTek5014(unittest.TestCase, AWGTestHelper, TestSequences): - def setUp(self): - AWGTestHelper.__init__(self, TekPattern) - for name in ['TEK1', 'TEK2']: - for ch in ['12', '34']: - channelName = name + '-' + ch - channel = PhysicalQuadratureChannel(label=channelName) - channel.sampling_rate = 1.2e9 - channel.instrument = name - channel.translator = 'TekPattern' - self.channels[channelName] = channel - - for m in ['1m1', '1m2', '2m1', '2m2', '3m1', '3m2', '4m1', '4m2']: - channelName = "{0}-{1}".format(name, m) - channel = PhysicalMarkerChannel(label=channelName) - channel.sampling_rate = 1.2e9 - channel.instrument = name - channel.translator = 'TekPattern' - self.channels[channelName] = channel - - mapping = {'digitizerTrig': 'TEK1-1m2', - 'slave_trig': 'TEK1-2m2', - 'q1': 'TEK1-12', - 'M-q1': 'TEK1-12', - 'M-q1-gate': 'TEK1-1m1', - 'q1-gate': 'TEK1-2m1', - 'q2': 'TEK1-34', - 'M-q2': 'TEK1-34', - 'M-q2-gate': 'TEK1-3m1', - 'q2-gate': 'TEK1-4m1', - 'cr': 'TEK2-12', - 'cr-gate': 'TEK2-1m1', - 'M-q1q2': 'TEK2-34', - 'M-q1q2-gate': 'TEK2-2m1'} - - self.finalize_map(mapping) - - @unittest.skip("Tek5014 unused in years") - def test_misc_seqs2(self): - """ Fails due to a divide by zero - File "C:\Projects\Q\lib\PyQLab\QGL\TekPattern.py", line 77, in merge_waveform - for entry in chAB['linkList'][n % len(chAB['linkList'])]: - ZeroDivisionError: integer division or modulo by zero - """ - TestSequences.test_misc_seqs2(self) - - @unittest.skip("Tek5014 unused in years") - def test_misc_seqs5(self): - """ Fails due to a divide by zero - File "C:\Projects\Q\lib\PyQLab\QGL\TekPattern.py", line 77, in merge_waveform - for entry in chAB['linkList'][n % len(chAB['linkList'])]: - ZeroDivisionError: integer division or modulo by zero - """ - TestSequences.test_misc_seqs5(self) - - # multiple tests will fail with an attribute error: - # AttributeError: 'Wait' object has no attribute 'isTimeAmp' at line 78 - # in TekPattern.py in merge_waveform - - @unittest.skip("Tek5014 unused in years") - def test_misc_seqs1(self): - TestSequences.test_misc_seqs1(self) - - @unittest.skip("Tek5014 unused in years") - def test_misc_seqs3(self): - TestSequences.test_misc_seqs3(self) - - @unittest.skip("Tek5014 unused in years") - def test_misc_seqs4(self): - TestSequences.test_misc_seqs4(self) - - @unittest.skip("Tek5014 unused in years") - def test_mux_CR(self): - TestSequences.test_mux_CR(self) - - @unittest.skip("Tek5014 unused in years") - def test_AllXY(self): - TestSequences.test_AllXY(self) - - @unittest.skip("Tek5014 unused in years") - def test_CR_PiRabi(self): - TestSequences.test_CR_PiRabi(self) - - @unittest.skip("Tek5014 unused in years") - def test_CR_EchoCRLen(self): - TestSequences.test_CR_EchoCRLen(self) - - @unittest.skip("Tek5014 unused in years") - def test_CR_EchoCRPhase(self): - TestSequences.test_CR_EchoCRPhase(self) - - @unittest.skip("Tek5014 unused in years") - def test_Decoupling_HannEcho(self): - TestSequences.test_Decoupling_HannEcho(self) - - @unittest.skip("Tek5014 unused in years") - def test_Decoupling_CPMG(self): - TestSequences.test_Decoupling_CPMG(self) - - @unittest.skip("Tek5014 unused in years") - def test_FlipFlop(self): - TestSequences.test_FlipFlop(self) - - @unittest.skip("Tek5014 unused in years") - def test_T1T2_InversionRecovery(self): - TestSequences.test_T1T2_InversionRecovery(self) - - @unittest.skip("Tek5014 unused in years") - def test_T1T2_Ramsey(self): - TestSequences.test_T1T2_Ramsey(self) - - @unittest.skip("Tek5014 unused in years") - def test_SPAM(self): - TestSequences.test_SPAM(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_RabiAmp(self): - TestSequences.test_Rabi_RabiAmp(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_RabiWidth(self): - TestSequences.test_Rabi_RabiWidth(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_RabiAmp_NQubits(self): - TestSequences.test_Rabi_RabiAmp_NQubits(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_RabiAmpPi(self): - TestSequences.test_Rabi_RabiAmpPi(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_SingleShot(self): - TestSequences.test_Rabi_SingleShot(self) - - @unittest.skip("Tek5014 unused in years") - def test_Rabi_PulsedSpec(self): - TestSequences.test_Rabi_PulsedSpec(self) - - @unittest.skip("Tek5014 unused in years") - def test_RB_SingleQubitRB(self): - TestSequences.test_RB_SingleQubitRB(self) - - @unittest.skip("Tek5014 unused in years") - def test_RB_SimultaneousRB_AC(self): - TestSequences.test_RB_SimultaneousRB_AC(self) - -# class TestTek7000(unittest.TestCase, AWGTestHelper, TestSequences): - -# def setUp(self): -# AWGTestHelper.__init__(self, TekPattern.read_Tek_file) -# for name in ['TEK1', 'TEK2', 'TEK3', 'TEK4', 'TEK5']: -# self.instruments[name] = Tek7000(label=name) - -# for ch in ['12']: -# channelName = name + '-' + ch -# channel = PhysicalQuadratureChannel(label=channelName) -# channel.instrument = self.instruments[name] -# self.channels[channelName] = channel - -# for m in ['1m1', '1m2', '2m1', '2m2']: -# channelName = "{0}-{1}".format(name,m) -# channel = PhysicalMarkerChannel(label=channelName) -# channel.instrument = self.instruments[name] -# self.channels[channelName] = channel - -# mapping = { 'digitizerTrig' :'TEK1-1m2', -# 'slave_trig' :'TEK1-2m2', -# 'q1' :'TEK1-12', -# 'M-q1' :'TEK2-12', -# 'M-q1-gate' :'TEK1-1m1', -# 'q1-gate' :'TEK1-2m1', -# 'q2' :'TEK3-12', -# 'M-q2' :'TEK4-12', -# 'M-q2-gate' :'TEK2-1m1', -# 'q2-gate' :'TEK2-2m1', -# 'cr' :'TEK5-12', -# 'cr-gate' :'TEK5-1m1'} -# self.finalize_map(mapping) - if __name__ == "__main__": unittest.main() diff --git a/tests/test_config.py b/tests/test_config.py index 41e5bea3..1513abfe 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -38,6 +38,7 @@ def setUp(self): def tearDown(self): shutil.rmtree('./tmp') + @unittest.skip("Need to update config API") def test_env(self): """ Test that if the BBN_MEAS_FILE environment variable is set, it is used @@ -59,7 +60,7 @@ def test_env(self): assert QGL.config.meas_file == meas_name assert QGL.config.AWGDir == os.path.realpath("./foo/bar/xyz") - + @unittest.skip("Need to update config API") def test_override1(self): """ Tests manually supplying a different config file when instantiating the channel library. diff --git a/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.aps1 b/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.aps1 new file mode 100644 index 00000000..9578434c --- /dev/null +++ b/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93a7ed05a9c679de05915e51500f6d9ee9d4e5ef0016b1a8c2ff26bdf622b1e0 +size 3991 diff --git a/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.h5 b/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.h5 deleted file mode 100644 index d4b9ab22..00000000 --- a/tests/test_data/awg/TestAPS1/AllXY/AllXY-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:598ec4cd4a90c6ef37b3bf78a6a07e093dafd68b23037179dc8f3ee604196ff3 -size 20568 diff --git a/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.aps1 b/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.aps1 new file mode 100644 index 00000000..7f055d16 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f224b52bf73aeb376166df84f6f166e5d48a7c4a2214a73fd40e41c3ef52e96b +size 2357 diff --git a/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.h5 b/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.h5 deleted file mode 100644 index 8e80f58b..00000000 --- a/tests/test_data/awg/TestAPS1/CPMG/CPMG-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd0994b6ef60cc0a19315aa45512f1c7f6a6612ce06895f161f4ae60fa7917d7 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.aps1 b/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.aps1 new file mode 100644 index 00000000..42b91ac5 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b35762b99a622467e594bf295ed35d923ff944bc6aa6c07a7832895a0c53f8f6 +size 2927 diff --git a/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.h5 b/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.h5 deleted file mode 100644 index 00c28e4d..00000000 --- a/tests/test_data/awg/TestAPS1/Echo/Echo-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0f14162bcf50abb771326b2db3ea36288e704d1224dbd1660dbec60de215121f -size 20568 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.aps1 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.aps1 new file mode 100644 index 00000000..9bb93800 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9fe524d7623feccacec0293a877c02afc44f75ee77d1d5269f795a85de341b7c +size 4209 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.h5 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.h5 deleted file mode 100644 index 0f589d2c..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1e0f1039e90c8361735fe98ddbd24e434fb9b760169a62ec946ae40274d1a60 -size 20552 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.aps1 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.aps1 new file mode 100644 index 00000000..969d00e7 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e3dc99287d4dc53f54900f61f8c3390214e6dbaeb065f991a9dd513a83bd63d +size 3149 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.h5 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.h5 deleted file mode 100644 index b5872b5f..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:92b69fd2c1d4208e22cb652dfac0e78de7d7502fc1a0028e4df32c7319cd9d02 -size 20552 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.aps1 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.aps1 new file mode 100644 index 00000000..67db4db5 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e7b0034fd155a7fd2d37388d977b0af521b194b1c47b3e8f78d5fa86b22861d +size 3369 diff --git a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.h5 b/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.h5 deleted file mode 100644 index 953bfa04..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRLen/EchoCR/EchoCR-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa055382df427f2625eb61ec6c112603c36891bf69e2e2d5037e2ef0af8d725b -size 18136 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.aps1 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.aps1 new file mode 100644 index 00000000..b30daca4 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71c17a0aa26078892e47aeb2ae0dcea71532b6b614a42ad90a15f7a07c1e25ab +size 4209 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.h5 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.h5 deleted file mode 100644 index 9c6f0102..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e1bc671bcfbba1005d9e593edf45288d0b6d830ff0445cf6c9360c31daa0753b -size 20552 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.aps1 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.aps1 new file mode 100644 index 00000000..0b249f5b --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3059c3d4b37c9f9de1e95e31f3a14bcdfd8f1017189ef697bbaeab4419dd8caa +size 3513 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.h5 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.h5 deleted file mode 100644 index 041cb89c..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e1b9e57467e487b23c15743b839e640c168bb5b0fe48fc55df83ade33e69558 -size 20552 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.aps1 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.aps1 new file mode 100644 index 00000000..7c0fccb8 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b99cd5f2d629ff33ee53b070b0a687d000fa9681bcaac3bbd3b3a71ec87e0ccb +size 11409 diff --git a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.h5 b/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.h5 deleted file mode 100644 index 9898ef3b..00000000 --- a/tests/test_data/awg/TestAPS1/EchoCRPhase/EchoCR/EchoCR-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c5e77f05e76a9b655cccc9c76aae4f3e412c88f4e7259b18db9a2a1b21c0fe4e -size 26992 diff --git a/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.aps1 b/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.aps1 new file mode 100644 index 00000000..e185c0d9 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8dcc6f62fb04a90ae74b6b80f2963736145fcd3672762641ac1dcc74c6f0c985 +size 23531 diff --git a/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.h5 b/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.h5 deleted file mode 100644 index 5c65333c..00000000 --- a/tests/test_data/awg/TestAPS1/FlipFlop/FlipFlop-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:757f73118a7c633b5d5161401bab8443bb4bb98a965b1f9978c71f9d0d694149 -size 41192 diff --git a/tests/test_data/awg/TestAPS1/GST/GST/listOfExperiments.npy b/tests/test_data/awg/TestAPS1/GST/GST/listOfExperiments.npy new file mode 100644 index 00000000..7e552e2d Binary files /dev/null and b/tests/test_data/awg/TestAPS1/GST/GST/listOfExperiments.npy differ diff --git a/tests/test_data/awg/TestAPS1/GST/GST2Q/listOfExperiments.npy b/tests/test_data/awg/TestAPS1/GST/GST2Q/listOfExperiments.npy new file mode 100644 index 00000000..44e229ed Binary files /dev/null and b/tests/test_data/awg/TestAPS1/GST/GST2Q/listOfExperiments.npy differ diff --git a/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.aps1 b/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.aps1 new file mode 100644 index 00000000..eb78325e --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0082cb2b408b942eac05a48e77344cb3f63edd606f6a7849041652b8f2852559 +size 3843 diff --git a/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.h5 b/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.h5 deleted file mode 100644 index 74151403..00000000 --- a/tests/test_data/awg/TestAPS1/MISC1/MISC1-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:964f74ba4a169ab0f60f9f39aeaa4f497f7a63f339d4773ee5e4b563b8859056 -size 20568 diff --git a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.aps1 b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.aps1 new file mode 100644 index 00000000..c79110f8 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b4d6e3c6244e4efad5925136379931db5be619a147bd82f9e6e2b7ae92e1397 +size 659 diff --git a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.h5 b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.h5 deleted file mode 100644 index adc1bfc8..00000000 --- a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f7e131852cac2f0b8dc2a9dbcd738be9dc1b5e8bc0323d06362c5d5a49cc372 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.aps1 b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.aps1 new file mode 100644 index 00000000..386f8af3 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11a4702cfb925a868d316c4549786d225e0ac115a8395640522c9221ab4e5b74 +size 755 diff --git a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.h5 b/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.h5 deleted file mode 100644 index 43c67a89..00000000 --- a/tests/test_data/awg/TestAPS1/MISC2/MISC2-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:79a4a4a1cf2cab3bedbf060b4dc4bf7166eaabe7781de4dcc0bf9d1923075b5f -size 16104 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.aps1 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.aps1 new file mode 100644 index 00000000..673bf3d7 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efe2ba032c43485ea55dd8b9cc9470ce19968eca2dabf744a958f7d6a369cefe +size 685 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.h5 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.h5 deleted file mode 100644 index e9be50b1..00000000 --- a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d059bb8d6ea48d80336179c280d8fbff658165f7823b85f173dd541205068ca -size 18520 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.aps1 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.aps1 new file mode 100644 index 00000000..197a426e --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f711c3304df1cfc8c32f5ae85de38023c33f070bd89b86752ad09992e35c37e9 +size 443 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.h5 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.h5 deleted file mode 100644 index ee2a676f..00000000 --- a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:85c3c4ede4a0cc4f75fe45a99c712982af0a90cd12e3131bbc447f460e379384 -size 16104 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.aps1 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.aps1 new file mode 100644 index 00000000..d076e9bf --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb173426f6db57e38d836a81eebb96058918ef7403406184ece584fd447599ac +size 755 diff --git a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.h5 b/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.h5 deleted file mode 100644 index f5180ba9..00000000 --- a/tests/test_data/awg/TestAPS1/MISC3/MISC3-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a79d97a95d1f4d010df4f9a9116d92099d9920c3fec64cf456d1ba71fcb4c506 -size 16104 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.aps1 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.aps1 new file mode 100644 index 00000000..f4984818 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9f9c622f7a08a002c42b382b3c2b12ecc97f3625c79e9cb64dae118af52570f +size 1151 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.h5 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.h5 deleted file mode 100644 index 8c50f48f..00000000 --- a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c0e436ad63f7ce73f53211ce6ceeff3e2d4d880fbeb6c942e16142f3294deab2 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.aps1 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.aps1 new file mode 100644 index 00000000..28147007 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3faa203b1c058d66a6499f9aba6e1cc04d49129e973bc131f900b26fc5c1ebfd +size 905 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.h5 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.h5 deleted file mode 100644 index 85cf1477..00000000 --- a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a0915cda20a3a66881b7701da17189c2be8dda857dcbe7180ac27ec8509c3b51 -size 16104 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.aps1 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.aps1 new file mode 100644 index 00000000..6161fa40 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ef90629a3658816f53523c9e2e80d96705187bd68e835f0d468dda368e9a694 +size 775 diff --git a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.h5 b/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.h5 deleted file mode 100644 index 7c6ded4c..00000000 --- a/tests/test_data/awg/TestAPS1/MISC4/MISC4-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65be23387c62f3a8a08547cea77a6e9ff8c649301fe60b33bacfbd96fc9433a5 -size 16104 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.aps1 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.aps1 new file mode 100644 index 00000000..10fc0bb5 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2979185871f56a5143138c031de487b54aacc4a4085689f6b630a48d5afd440 +size 2999 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.h5 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.h5 deleted file mode 100644 index bb89df1a..00000000 --- a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:665f63cb2a9ba48fdd3e890c3db66f0607d4e20263d8d77db35c77bfda76c63c -size 20568 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.aps1 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.aps1 new file mode 100644 index 00000000..2b990dea --- /dev/null +++ b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca5bdf91c5f9d3d1d4c4ac67bad05c6418a4db32c53949a82adfa82a86289800 +size 2379 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.h5 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.h5 deleted file mode 100644 index 99029ac8..00000000 --- a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99adec81a02115317caeddc332063fef5fd5bcb5342a3a15ad92fb5567a6c3fc -size 18520 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.aps1 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.aps1 new file mode 100644 index 00000000..a6e4f937 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:269cf8968cc6d1c11426b6db80ba679e50269528eebff2647a4d64376f8e1cf9 +size 1889 diff --git a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.h5 b/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.h5 deleted file mode 100644 index dce42a8f..00000000 --- a/tests/test_data/awg/TestAPS1/PiRabi/PiRabi-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6dc366b846ff17aea66ecfe7154088da73ae3803033c3ba2a90cba8ab4b3ac13 -size 16104 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.aps1 b/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.aps1 new file mode 100644 index 00000000..4bc0eb82 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03384c3fcbe4ebeb39a43df1e47173d5276ff431c44cd10c6a5891414c12022d +size 2905 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.h5 deleted file mode 100644 index e21de48c..00000000 --- a/tests/test_data/awg/TestAPS1/RabiAmp/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1878b25a724b98b176070fbb562b7a54ba4f6d0ca67724e4b5bc31a43e491fae -size 20568 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.aps1 b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.aps1 new file mode 100644 index 00000000..4bc0eb82 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03384c3fcbe4ebeb39a43df1e47173d5276ff431c44cd10c6a5891414c12022d +size 2905 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.h5 deleted file mode 100644 index e21de48c..00000000 --- a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1878b25a724b98b176070fbb562b7a54ba4f6d0ca67724e4b5bc31a43e491fae -size 20568 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.aps1 b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.aps1 new file mode 100644 index 00000000..ce5c9406 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e5c52c3c9a278381d328e3388d75d4d2296041c0c1a6c1c0a3083a8459b087f +size 2805 diff --git a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.h5 b/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.h5 deleted file mode 100644 index 110969d5..00000000 --- a/tests/test_data/awg/TestAPS1/RabiAmp2/Rabi/Rabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:db62cca9c591811789eb181b4c0ddb0a904ce2dc7d05e7fb8050033daefd6ee0 -size 20568 diff --git a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.aps1 b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.aps1 new file mode 100644 index 00000000..2a6a3109 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac20319939b6dc7f0d64a1347a82bb9b671f767fe8b5e7a1bc06794d3d8cf77 +size 2425 diff --git a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.h5 deleted file mode 100644 index db4fa613..00000000 --- a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:757050fe27d6d6fcbfc2d9d4b6b02d09745ef75948e7012f8ffab9cc520bac99 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.aps1 b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.aps1 new file mode 100644 index 00000000..82b0b907 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9757b597ae5551218c1368ee3db777a3b411faed53fa7485d879b1c5a804856a +size 1839 diff --git a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.h5 b/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.h5 deleted file mode 100644 index b9c277eb..00000000 --- a/tests/test_data/awg/TestAPS1/RabiAmpPi/Rabi/Rabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ea5abdf66a0317b1ac458e9a102a0f4feb1850f3f3f7114b310eee161804ee50 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.aps1 b/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.aps1 new file mode 100644 index 00000000..afc9515c --- /dev/null +++ b/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30c8ee6a5193280bdc158fdd762c7c05a744dc78045dc9100286b3dd501f9e24 +size 13 diff --git a/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.h5 deleted file mode 100644 index 1c37d756..00000000 --- a/tests/test_data/awg/TestAPS1/RabiWidth/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f450ffb720bb132c6db69679f24efaeace7ac3e377a089205025af9d1394f3b -size 6240 diff --git a/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.aps1 b/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.aps1 new file mode 100644 index 00000000..084ba0e7 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ed98961c6bcb69b90e43cfc6eb4369e94070691496236fd2ccf9df913fe0624 +size 2363 diff --git a/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.h5 b/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.h5 deleted file mode 100644 index 14734f5a..00000000 --- a/tests/test_data/awg/TestAPS1/Ramsey/Ramsey-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3783ad1b01a211e762dc1f7ff450852792638d739caabe2a2e4f735ef195e95d -size 18520 diff --git a/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.aps1 b/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.aps1 new file mode 100644 index 00000000..7bdf4f68 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:332f9f54ee51746281533a5c854afe85e924763bd80a5aa07d51a76fb16cfb63 +size 39821 diff --git a/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.h5 b/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.h5 deleted file mode 100644 index 73756191..00000000 --- a/tests/test_data/awg/TestAPS1/SPAM/SPAM-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:90c2eb18127ca1d8811d3d5cc3522f16f19748279ffc003d421b0181bdbd351f -size 56762 diff --git a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.aps1 b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.aps1 new file mode 100644 index 00000000..afc9515c --- /dev/null +++ b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30c8ee6a5193280bdc158fdd762c7c05a744dc78045dc9100286b3dd501f9e24 +size 13 diff --git a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.h5 b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.h5 deleted file mode 100644 index 1c37d756..00000000 --- a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f450ffb720bb132c6db69679f24efaeace7ac3e377a089205025af9d1394f3b -size 6240 diff --git a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.aps1 b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.aps1 new file mode 100644 index 00000000..afc9515c --- /dev/null +++ b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30c8ee6a5193280bdc158fdd762c7c05a744dc78045dc9100286b3dd501f9e24 +size 13 diff --git a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.h5 b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.h5 deleted file mode 100644 index 1c37d756..00000000 --- a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f450ffb720bb132c6db69679f24efaeace7ac3e377a089205025af9d1394f3b -size 6240 diff --git a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2_py27.h5 b/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2_py27.h5 deleted file mode 100644 index 39bfc4da..00000000 --- a/tests/test_data/awg/TestAPS1/SimultaneousRB_AC/RB/RB-APS2_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dcc7226c4d9e8f9f5e56794d7e057003af6eaaecd4c841fdef2fedc2bf9b45f1 -size 6240 diff --git a/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.aps1 b/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.aps1 new file mode 100644 index 00000000..0b1b623e --- /dev/null +++ b/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:904e7c9a02ec999e6fc7aaa2f28a98384eb67a4a031319b5c799dbd2aa998be2 +size 121307 diff --git a/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.h5 b/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.h5 deleted file mode 100644 index 128fe7e0..00000000 --- a/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:18a60bc56608e36d178c60119cb9526ad4caa68f520aa8f5c2924db45342b31a -size 138680 diff --git a/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1_py27.h5 b/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1_py27.h5 deleted file mode 100644 index 748f1796..00000000 --- a/tests/test_data/awg/TestAPS1/SingleQubitRB/RB/RB-APS1_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a322f8589452532de3f3d7feeefd1e58dbb83796250e37529c854deef24f1534 -size 138680 diff --git a/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.aps1 b/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.aps1 new file mode 100644 index 00000000..4012d581 --- /dev/null +++ b/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13fc8118413ab1d83e6390cb06029e66aa126d33cc8404d92f0123da772705fb +size 1149 diff --git a/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.h5 b/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.h5 deleted file mode 100644 index 4f0f920c..00000000 --- a/tests/test_data/awg/TestAPS1/SingleShot/SingleShot-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0c5996784d291c3dde24b082854188a5704304e70be802478a07ededf6993e92 -size 18520 diff --git a/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.aps1 b/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.aps1 new file mode 100644 index 00000000..b4b0497d --- /dev/null +++ b/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40da4a38af7ff4312e61f0055908cd6273beaa80be8fdd70581a8a2154ca12b1 +size 1109 diff --git a/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.h5 b/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.h5 deleted file mode 100644 index f4f6922a..00000000 --- a/tests/test_data/awg/TestAPS1/Spec/Spec-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ea122c4f469e951782d29dc14dc83878dcad293e6e54ac284a3940186b32c30b -size 18520 diff --git a/tests/test_data/awg/TestAPS1/T1/T1-APS1.aps1 b/tests/test_data/awg/TestAPS1/T1/T1-APS1.aps1 new file mode 100644 index 00000000..44568cfc --- /dev/null +++ b/tests/test_data/awg/TestAPS1/T1/T1-APS1.aps1 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8613cbca09ccd2a961c84c340b50414cbdef98be371675f39ff64f31ced993da +size 1909 diff --git a/tests/test_data/awg/TestAPS1/T1/T1-APS1.h5 b/tests/test_data/awg/TestAPS1/T1/T1-APS1.h5 deleted file mode 100644 index 63c12621..00000000 --- a/tests/test_data/awg/TestAPS1/T1/T1-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd60ddb02bfb69b40191e2d93683ced7d77f409d160af71f489bb9f28e174651 -size 18520 diff --git a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.aps2 b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.aps2 new file mode 100644 index 00000000..c4cf5611 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84c8e5cc7c128b976fb19122933276d9a1263524fd17a016764d10b3992480f4 +size 5550 diff --git a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.h5 b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.h5 deleted file mode 100644 index b4146f64..00000000 --- a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fbc0210f06102970cce4b843f2d11080ae9a47824cabc6bcc0c6cb7791675819 -size 14128 diff --git a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.aps2 b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.aps2 new file mode 100644 index 00000000..b7b1c359 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f601221c8a1df53d6defc97aba63c77780e9b97d69726c6a3b0b9ef987e2cb89 +size 2894 diff --git a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.h5 b/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.h5 deleted file mode 100644 index 63de3f69..00000000 --- a/tests/test_data/awg/TestAPS2/AllXY/AllXY-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b78617f09c3fc6e4e9ec43d35f512be6422750099e532c0a843e0f570b2ad7c1 -size 11472 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.aps2 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.aps2 new file mode 100644 index 00000000..c57aa3f2 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f847ac93b35b559fbe0afab344c8d23ef064b4ac5c2bc9612b6723cd680e1ff +size 854 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.h5 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.h5 deleted file mode 100644 index e8522425..00000000 --- a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1aa4d2064d8c94bd5a2c861f5137c74b47bac9912de8e362650de79b9353632 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.aps2 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.aps2 new file mode 100644 index 00000000..2d360388 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2127036b39a846267d5a4cd8b5659abed0d8bcd22b200acbaf0f30265e23d2d +size 278 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.h5 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.h5 deleted file mode 100644 index 16aa0539..00000000 --- a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e656cf6d7f1ec5d289c44dfdf3395c21b5002cfa0d099106e28d1bb279ee998c -size 10664 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.aps2 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.aps2 new file mode 100644 index 00000000..148df35e --- /dev/null +++ b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:142a223f060a567f1fc94f06817e41256779fea86bd04cf006a000a284cfb680 +size 98 diff --git a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.h5 b/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.h5 deleted file mode 100644 index cf8c86e4..00000000 --- a/tests/test_data/awg/TestAPS2/CNOT_CR_mux/CNOT_CR_mux-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7248ddc03f87ba4062fb2cfdd5c8e9ff4c916a0bbff610de2ee4a13b3c9b09c9 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.aps2 b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.aps2 new file mode 100644 index 00000000..87cf1736 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3be613e095ae800922fe93d3d1511cbba01fa2a9955578c53d7dcbaf68c8e012 +size 1982 diff --git a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.h5 b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.h5 deleted file mode 100644 index d5777ec0..00000000 --- a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2e2e47343922a82e1258e6510001963cdd46acb7a7841565704c0175f255136a -size 10664 diff --git a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.aps2 b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.aps2 new file mode 100644 index 00000000..11ea6c5c --- /dev/null +++ b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab7bdc5ad53a54bf0ef6eb859d746255df47be061489b93e3c5a733060085425 +size 1246 diff --git a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.h5 b/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.h5 deleted file mode 100644 index 377ce4bc..00000000 --- a/tests/test_data/awg/TestAPS2/CPMG/CPMG-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d5be72267a5b599abcce2bcdf9968da5b9dfaab58cee5cf472c8fe8f3dce8cc -size 10664 diff --git a/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.aps2 b/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.aps2 new file mode 100644 index 00000000..7ef6e389 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8777be258150c69db56d7bf5446bdbf07b44eab9d1cd07ca85afb609c2f4677 +size 2886 diff --git a/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.h5 b/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.h5 deleted file mode 100644 index 176b812c..00000000 --- a/tests/test_data/awg/TestAPS2/Echo/Echo-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4321e2efd619bb40368ad6238687cd97f465c94909f3969a4d80a5a09de36efc -size 11464 diff --git a/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.aps2 b/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.aps2 new file mode 100644 index 00000000..d5e38136 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b87d3f879174b7af4502443943bc099eb69a9a559df4ba618cd52b084ae0d9ae +size 1598 diff --git a/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.h5 b/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.h5 deleted file mode 100644 index a62f3b9d..00000000 --- a/tests/test_data/awg/TestAPS2/Echo/Echo-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2354707a7b3471650d08145218677beb569d9ea2d87283b56ad84473dfed599 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.aps2 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.aps2 new file mode 100644 index 00000000..f9ce9f77 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27882f98f2386e02b8f7bab8dc0cbbc9c70f8892a621e8f07d550f87392eaf8e +size 4310 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.h5 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.h5 deleted file mode 100644 index ab15aa85..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:074d02801fc6b663db6f9250ceb639ca7b2e755ddb04ae70f3b9dd87e50c586c -size 12792 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.aps2 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.aps2 new file mode 100644 index 00000000..5ff1fa82 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27544612cfc2a8f7e8b9b1306672e5f9ecf16b8b22712de3482797da6417ea3b +size 2862 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.h5 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.h5 deleted file mode 100644 index 9d8b12af..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61084d6ac1164b7568c446759cb0baca6d850926162b7adc3073d4caa2aed0c7 -size 11344 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.aps2 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.aps2 new file mode 100644 index 00000000..bad77e86 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:094c46db9912e1a4a1c2e5fd3f4e8affb52ff59b84e17b042a75d6dfc4c86f7d +size 2318 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.h5 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.h5 deleted file mode 100644 index 0ab91628..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6749480ab0b75672d39dd6005238719b1e76e3b3f9e6814894220076158ee1aa -size 10800 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.aps2 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.aps2 new file mode 100644 index 00000000..5ff1fa82 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27544612cfc2a8f7e8b9b1306672e5f9ecf16b8b22712de3482797da6417ea3b +size 2862 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.h5 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.h5 deleted file mode 100644 index 9d8b12af..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61084d6ac1164b7568c446759cb0baca6d850926162b7adc3073d4caa2aed0c7 -size 11344 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.aps2 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.aps2 new file mode 100644 index 00000000..1957c297 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c596ac8bb53ceb5afbaaa2a76eeec682298d26e4e11aca1694d060fdaffbe507 +size 5710 diff --git a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.h5 b/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.h5 deleted file mode 100644 index fae1d541..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRLen/EchoCR/EchoCR-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e7da7ea9ae19ea57b6e1cc5783c4ebb53ad2522ef51979d1fb656738ecc0aaf6 -size 14192 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.aps2 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.aps2 new file mode 100644 index 00000000..c14e60e7 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5c00e601b1472df2167f948d585a951e4c8f369785db23f91a94ea9a8de7ed4 +size 4310 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.h5 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.h5 deleted file mode 100644 index 8696d76b..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aace28a1695a9111804ab0bec5d783d482b835646ef86ca46e8e72b95092c8eb -size 12792 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.aps2 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.aps2 new file mode 100644 index 00000000..1b50f181 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8989adb01d5d1b23c36bebcfa6707a1000fab28057cec9f6ddeb3d385c0cfb70 +size 2862 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.h5 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.h5 deleted file mode 100644 index 0779fc89..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:31849839f1cef008563c60475daae27687e16d87fd14f793eabdf80b4140cdc6 -size 11344 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.aps2 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.aps2 new file mode 100644 index 00000000..3f26f413 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67e54be6fc7da5fea7b15ee46bdeb84aa97483cd1f5da827f298be78a75e28e6 +size 2814 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.h5 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.h5 deleted file mode 100644 index 3944eb32..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4e95177c552f582aa32d9fac036db4cc9acd19214eabb4d74bec2a31fbb885f -size 11296 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.aps2 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.aps2 new file mode 100644 index 00000000..1b50f181 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8989adb01d5d1b23c36bebcfa6707a1000fab28057cec9f6ddeb3d385c0cfb70 +size 2862 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.h5 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.h5 deleted file mode 100644 index 9220854d..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f2000631a2233d3c5b19d2fa7e53d5c6b65f3a09433bd0b8aedc85906d9bccc3 -size 11344 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.aps2 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.aps2 new file mode 100644 index 00000000..c2d1bbd1 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:998ed2c3fb7c85f69823c69e6ce567ead8a65003fe9df78e4d4891bd95a89493 +size 13758 diff --git a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.h5 b/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.h5 deleted file mode 100644 index 043f2ada..00000000 --- a/tests/test_data/awg/TestAPS2/EchoCRPhase/EchoCR/EchoCR-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f8df32e2cf8c12ad3b48430f82500f8aa5fcdbf20d321825ae1f487d6f091db -size 22240 diff --git a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.aps2 b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.aps2 new file mode 100644 index 00000000..591b20d6 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b1ab91da85f6996eb88a4f480dc646247cf284a1cf2c6f68cfc171b1c11cbb +size 27566 diff --git a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.h5 b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.h5 deleted file mode 100644 index a02c1072..00000000 --- a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:83900cc7545b582b4094661ffe46cdf13ae1b0c5fe0f26b81889c85e948482a6 -size 36144 diff --git a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.aps2 b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.aps2 new file mode 100644 index 00000000..5ceec56e --- /dev/null +++ b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1fa32e761c559b4d4f286bbb5a1203c5cc4b18554d4d72282716649eb68330c +size 15198 diff --git a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.h5 b/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.h5 deleted file mode 100644 index 35bb1250..00000000 --- a/tests/test_data/awg/TestAPS2/FlipFlop/FlipFlop-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cc3a30d96dafb22cd52d508ed0770c129fdf99338b33471480580fdf959eeed6 -size 23776 diff --git a/tests/test_data/awg/TestAPS2/GST/GST/listOfExperiments.npy b/tests/test_data/awg/TestAPS2/GST/GST/listOfExperiments.npy new file mode 100644 index 00000000..7e552e2d Binary files /dev/null and b/tests/test_data/awg/TestAPS2/GST/GST/listOfExperiments.npy differ diff --git a/tests/test_data/awg/TestAPS2/GST/GST2Q/listOfExperiments.npy b/tests/test_data/awg/TestAPS2/GST/GST2Q/listOfExperiments.npy new file mode 100644 index 00000000..44e229ed Binary files /dev/null and b/tests/test_data/awg/TestAPS2/GST/GST2Q/listOfExperiments.npy differ diff --git a/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.aps2 b/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.aps2 new file mode 100644 index 00000000..cbf62bbb --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb695b5795e4c1ab729d4800d939687489312e675b8bbb2bdde34d129d15a2f7 +size 3566 diff --git a/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.h5 b/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.h5 deleted file mode 100644 index b0a3a6a7..00000000 --- a/tests/test_data/awg/TestAPS2/MISC1/MISC1-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:86e48fbb5d9ee98c3c04a98c7a473d5ff61d41be88fbb73c7ad9cf4e5a005ce4 -size 12144 diff --git a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.aps2 b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.aps2 new file mode 100644 index 00000000..d7d18a41 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c9c042af3d9890243f33df8c82ad8858dca532e86115b33dbf065e8ecd6df7a +size 302 diff --git a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.h5 b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.h5 deleted file mode 100644 index 03a088e7..00000000 --- a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9adb85c5ce6cb9816addc5e8604b27a8111e6b28dde262f63dfc5057f9d7a06d -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.aps2 b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.aps2 new file mode 100644 index 00000000..73c2d580 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d8f4baee00287d69c030d07c58b55dabc45d4d4a68028c0b517c95c7f67ceae +size 638 diff --git a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.h5 b/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.h5 deleted file mode 100644 index c2c2df99..00000000 --- a/tests/test_data/awg/TestAPS2/MISC2/MISC2-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:915e457884f2c97a47c28d3d8c27390c9c8058262ce6394ccdf0b1c2d744abbf -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.aps2 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.aps2 new file mode 100644 index 00000000..05147f69 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2648062292b4b86379641948f42f9b3e580f061e646ebc719518fae5ae2b47b5 +size 366 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.h5 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.h5 deleted file mode 100644 index c51d3682..00000000 --- a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:416c37f8cdd7f8ce8bf1abe4b72a4173e3a661148e0db3aefe4d5665b1f0a147 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.aps2 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.aps2 new file mode 100644 index 00000000..2d360388 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2127036b39a846267d5a4cd8b5659abed0d8bcd22b200acbaf0f30265e23d2d +size 278 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.h5 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.h5 deleted file mode 100644 index 16aa0539..00000000 --- a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e656cf6d7f1ec5d289c44dfdf3395c21b5002cfa0d099106e28d1bb279ee998c -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.aps2 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.aps2 new file mode 100644 index 00000000..9e74a68a --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2e3ecdb003db075586c2a206bc7d7682b1ea64e298934c3f9d4fe5e80df989b +size 654 diff --git a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.h5 b/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.h5 deleted file mode 100644 index cee1a3cd..00000000 --- a/tests/test_data/awg/TestAPS2/MISC3/MISC3-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:effecd5635e103d6cfd24c33e8a2433c044c9ea8738f726d20db2d3a8688033b -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.aps2 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.aps2 new file mode 100644 index 00000000..7e82c465 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afc0ad90fef6b1152038b523a4d9e60ebe07b4b873118f5af886299d0c4084b3 +size 542 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.h5 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.h5 deleted file mode 100644 index 5c356fdd..00000000 --- a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ff47cb0de965b5eeee007073e18cf1595db07704bea14860301b4ebc7269558 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.aps2 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.aps2 new file mode 100644 index 00000000..9349b597 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30ae36b2e96aff26f55a71282a6e3c5dab02439e39c0ace27add0eea05383224 +size 790 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.h5 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.h5 deleted file mode 100644 index b43355ab..00000000 --- a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ad29c5d9ad6bdcf2d71e26167aced2f450382754cd23d764ad21165f2b268f15 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.aps2 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.aps2 new file mode 100644 index 00000000..e0e78833 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c561c0e4b1bfbe9f1cbb503eb755a0323b5be68ff3e7a145edfa27a324ed2a8 +size 694 diff --git a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.h5 b/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.h5 deleted file mode 100644 index 2276be6d..00000000 --- a/tests/test_data/awg/TestAPS2/MISC4/MISC4-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b101668cd5d7ea4ced46a8d357ce9145984d66bf18610f222df20666846fcdaf -size 10664 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.aps2 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.aps2 new file mode 100644 index 00000000..058335ff --- /dev/null +++ b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5db547eede6bb82dedff31595a5f103867edd64487509451e40be0f47fcc5431 +size 3166 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.h5 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.h5 deleted file mode 100644 index fa599be4..00000000 --- a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7c311beb3a70d927d1939705577029ae1939822593558d2cf1ba50cb3351cda7 -size 11744 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.aps2 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.aps2 new file mode 100644 index 00000000..30caceef --- /dev/null +++ b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5077d62fe51b3fad882dbd73f5783eb4aa0a9f8dcd2dd43d31d518878a95fc87 +size 2246 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.h5 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.h5 deleted file mode 100644 index b9f33eb5..00000000 --- a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81a88bcc43f757356ad54647b515bb508c7fd4767da4f806c48f20fc082af080 -size 10824 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.aps2 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.aps2 new file mode 100644 index 00000000..6aa6816e --- /dev/null +++ b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:365c689f3611c49bae72fde4db099063f1b6bcc6fc90b12bacef100f21f53647 +size 1702 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.h5 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.h5 deleted file mode 100644 index 69a02bfb..00000000 --- a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8960fdf72531618dbacf7c8b1c10334184a4a7ef6ded1c0fdadce1c002cfae77 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.aps2 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.aps2 new file mode 100644 index 00000000..30caceef --- /dev/null +++ b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5077d62fe51b3fad882dbd73f5783eb4aa0a9f8dcd2dd43d31d518878a95fc87 +size 2246 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.h5 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.h5 deleted file mode 100644 index b9f33eb5..00000000 --- a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81a88bcc43f757356ad54647b515bb508c7fd4767da4f806c48f20fc082af080 -size 10824 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.aps2 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.aps2 new file mode 100644 index 00000000..3577086d --- /dev/null +++ b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a005b4fab6c710c68cd3fa008ac4f25d4f8b4358f4d65f97a4cb4726e1098d32 +size 2614 diff --git a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.h5 b/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.h5 deleted file mode 100644 index 099c3395..00000000 --- a/tests/test_data/awg/TestAPS2/PiRabi/PiRabi-APS5.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d863d35d6ecf34db2e931f291c41f1d5e89a76c6dc56218f206397daf2eb411 -size 11192 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.aps2 new file mode 100644 index 00000000..e7d23b5e --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84c2f406fc1765013f9c203a8e6eaffc97cfc228a6bbb4a1ad235b7d55de2e63 +size 2590 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.h5 deleted file mode 100644 index 3c3c7192..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d054d3bf07b82bcd8fceb169441aa52653742fe6be83b2eb799fd339675ee120 -size 11168 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.aps2 new file mode 100644 index 00000000..e9188c2c --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:959f0c471be1bcf3fd7177b80184f464afa2657c80a29892f10ac62eb50754fa +size 1070 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.h5 b/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.h5 deleted file mode 100644 index 8ad9d24c..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp/Rabi/Rabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14db8318fc956cc9428038237eb83de6ef9d7dd8e343a627f5af6d8be8f2808b -size 10664 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.aps2 new file mode 100644 index 00000000..e7d23b5e --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84c2f406fc1765013f9c203a8e6eaffc97cfc228a6bbb4a1ad235b7d55de2e63 +size 2590 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.h5 deleted file mode 100644 index 3c3c7192..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d054d3bf07b82bcd8fceb169441aa52653742fe6be83b2eb799fd339675ee120 -size 11168 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.aps2 new file mode 100644 index 00000000..e9188c2c --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:959f0c471be1bcf3fd7177b80184f464afa2657c80a29892f10ac62eb50754fa +size 1070 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.h5 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.h5 deleted file mode 100644 index 8ad9d24c..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14db8318fc956cc9428038237eb83de6ef9d7dd8e343a627f5af6d8be8f2808b -size 10664 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.aps2 new file mode 100644 index 00000000..a4b21884 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0a75b4f3a1ac4fb541d65a89e1050ddf2d5b3827b3ef1d50d6d6a7daf0bde17 +size 2150 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.h5 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.h5 deleted file mode 100644 index 4eac161e..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:969244eeb80756e810991823154a170fd7c781eeb6e6458a5c29e72851547e93 -size 10728 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.aps2 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.aps2 new file mode 100644 index 00000000..e9188c2c --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:959f0c471be1bcf3fd7177b80184f464afa2657c80a29892f10ac62eb50754fa +size 1070 diff --git a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.h5 b/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.h5 deleted file mode 100644 index 8ad9d24c..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmp2/Rabi/Rabi-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14db8318fc956cc9428038237eb83de6ef9d7dd8e343a627f5af6d8be8f2808b -size 10664 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.aps2 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.aps2 new file mode 100644 index 00000000..f3e01bba --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6dd034f72cef034a68543bb4739f3748da2b8b978c2e8532e862c6cb4bb6ebbb +size 2718 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.h5 deleted file mode 100644 index 15c902a5..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d0775ac3780f687769e78cad08d9b7d92bf95e3e3c2f3050ce58a974f5fda4c7 -size 11296 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.aps2 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.aps2 new file mode 100644 index 00000000..1c87b609 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d47634aa2cc2809834475a0f117e9d9d828e85bca3b24e582affdc224a7b2f1 +size 1086 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.h5 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.h5 deleted file mode 100644 index 4c178a11..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3c7dc446b904881261db1c6633dd34ebae89e9c2ffc6889a54581bfdf7d25697 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.aps2 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.aps2 new file mode 100644 index 00000000..31bd854f --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fa84799426b4229cc3b14d4ee352d7e8086d1b4364ff12247302d7ae63f3124 +size 1246 diff --git a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.h5 b/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.h5 deleted file mode 100644 index 33dea5d2..00000000 --- a/tests/test_data/awg/TestAPS2/RabiAmpPi/Rabi/Rabi-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bdc238f311f839735033b037991ba9f78bc867ba8b1c6c8a15f235eaa66a0837 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.aps2 b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.aps2 new file mode 100644 index 00000000..10040774 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1760a6778f5be4e1ed2ff400754eed899bbfcb2eaf023ba549888d2f1761377c +size 133022 diff --git a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.h5 b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.h5 deleted file mode 100644 index 5259eba8..00000000 --- a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a339b76ebcc9d086cd3803a89b1c5e6c90b3fd06e103e450abe6d74648827995 -size 141600 diff --git a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.aps2 b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.aps2 new file mode 100644 index 00000000..9ec47b44 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63a70eb6ace79b1e32d3c4c84e8289ac6ff3bcf03b3af2a98b72becf1788497d +size 1070 diff --git a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.h5 b/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.h5 deleted file mode 100644 index bd8942d8..00000000 --- a/tests/test_data/awg/TestAPS2/RabiWidth/Rabi/Rabi-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec5f1a8ba8396b3ba1319ce825fc8e4ec0d9fc6415768905f758a15a54193f4b -size 10664 diff --git a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.aps2 b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.aps2 new file mode 100644 index 00000000..2e35f4eb --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ed0361d46fee45b792ab01bce498043fc666f814de55237f1fb5b6fc2d9876e +size 1982 diff --git a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.h5 b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.h5 deleted file mode 100644 index 40d604b3..00000000 --- a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ef6338bddfdcab213e12581b6a97b1316884838167748b0c5e98cd4330b64b22 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.aps2 b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.aps2 new file mode 100644 index 00000000..46375518 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9814858177b26e6d187ee30920547db85d9ac00e2a16c6260cb84a9a2aa9a8f +size 1430 diff --git a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.h5 b/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.h5 deleted file mode 100644 index ac0be242..00000000 --- a/tests/test_data/awg/TestAPS2/Ramsey/Ramsey-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c3cba432c0f7d9b7207a9ce43f8301c743c630271106d2a80712c89e75c46ef5 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.aps2 b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.aps2 new file mode 100644 index 00000000..05f7d108 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a347e86c8e15f8e8cc42c36f2c3fcd46cca15192d03ecf24de864a63f9ffed7 +size 40886 diff --git a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.h5 b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.h5 deleted file mode 100644 index 5fd4a6cb..00000000 --- a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43b14db680f80a369c2540c565cefac2a2870aea59c7bad31c05d2d74956c270 -size 49464 diff --git a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.aps2 b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.aps2 new file mode 100644 index 00000000..af7fa503 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:693869c98824b15aaf89f43edfab1005b6382564d16b8545b3f1a9c5d07634b8 +size 23118 diff --git a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.h5 b/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.h5 deleted file mode 100644 index 6583bfa6..00000000 --- a/tests/test_data/awg/TestAPS2/SPAM/SPAM-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54c4f9ef853fedffb8fa8715d725328e4af6d73e6027e8a38916ab914d76e729 -size 31696 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.aps2 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.aps2 new file mode 100644 index 00000000..ebad8370 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:714f3bf47f611b39dd0fd544b7d517a5cb99ca52bd86a748d27ac6dc2cc17bea +size 101214 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.h5 deleted file mode 100644 index d2e4d179..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd966f8d48d3cfa94237cc2c112b70157d35230ca2dcd4664bf4c4c731d3a061 -size 109792 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1_py27.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1_py27.h5 deleted file mode 100644 index dfca1f76..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS1_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:afa8cc3c99fea314c9e01d7159c8222932760cf47bc93ff6780452ebd4e7e14f -size 109792 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.aps2 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.aps2 new file mode 100644 index 00000000..5b941d80 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5281ef48b48391cbc4542ad51a21a7dcfb3d34556b535ac47e8946c5a526980a +size 40174 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.h5 deleted file mode 100644 index 13bd0b3a..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:222857cb4e7df9c271e1583a94d1e6696dd2c29104e7ee60dcfeace5b8af541a -size 48752 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2_py27.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2_py27.h5 deleted file mode 100644 index 2b9cb45f..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS2_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:09bf8d013355b15c3f97a641bb2d70eed3e28f4e0d678c718048634d447e60c3 -size 48752 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.aps2 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.aps2 new file mode 100644 index 00000000..f263f76a --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:153c21514cf092be2f49b28dd716a2ea3395b688dbe9d7a73122835f50aa8526 +size 94174 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.h5 deleted file mode 100644 index bb804166..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2af3590d082ccb86ee8593c3913f8b505dba80f7fae8a21fa7d763b5e753bd36 -size 102752 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3_py27.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3_py27.h5 deleted file mode 100644 index bc8caa68..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS3_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e42789e76e1d2e544847ddb2f4131198188a8aa5971097a537dd354fd8149bb1 -size 102752 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.aps2 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.aps2 new file mode 100644 index 00000000..5b941d80 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5281ef48b48391cbc4542ad51a21a7dcfb3d34556b535ac47e8946c5a526980a +size 40174 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.h5 deleted file mode 100644 index 13bd0b3a..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:222857cb4e7df9c271e1583a94d1e6696dd2c29104e7ee60dcfeace5b8af541a -size 48752 diff --git a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4_py27.h5 b/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4_py27.h5 deleted file mode 100644 index b3de0972..00000000 --- a/tests/test_data/awg/TestAPS2/SimultaneousRB_AC/RB/RB-APS4_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51493c82b6a380853c1644469efff8e2234c0233e48b5508759a066e1f16fc1b -size 48752 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.aps2 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.aps2 new file mode 100644 index 00000000..26476cff --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d08252ecf794842f96ea5b7b2132283e351316258b1d42c963fc507e02034c5 +size 113798 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.h5 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.h5 deleted file mode 100644 index 062da429..00000000 --- a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd2e0d3b890dc1010ad4b55381c11b6f7744a8c58106c950d7a445620fdf8c44 -size 122376 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1_py27.h5 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1_py27.h5 deleted file mode 100644 index d86f0f00..00000000 --- a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS1_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43e610294922c1e73d59fcdb0c6473d9f9c2338c3d8351c2dd6a2eda075fa55d -size 122376 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.aps2 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.aps2 new file mode 100644 index 00000000..71ed0ab7 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb7f55567c34c01fe5d88a02cdb2fdff6ad554eda1622d7aa5524c0d5abd038c +size 68670 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.h5 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.h5 deleted file mode 100644 index dacb3ba2..00000000 --- a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e805e568677dda8a06e7070204af604ed0b84926b4cf1fc0dbe617d8a13b5a9 -size 77248 diff --git a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2_py27.h5 b/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2_py27.h5 deleted file mode 100644 index 23bf2dfa..00000000 --- a/tests/test_data/awg/TestAPS2/SingleQubitRB/RB/RB-APS2_py27.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8792254cb7b487fdc6cde009a8950654b674d4a31903f875f056399131db928c -size 77248 diff --git a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.aps2 b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.aps2 new file mode 100644 index 00000000..1cfc0072 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6697f675afe2b24ec3ba066632789487de2c4382d9592a2c22286d472c88fe5 +size 374 diff --git a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.h5 b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.h5 deleted file mode 100644 index 6d9c8d34..00000000 --- a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fecac08fc9b57eb04f0d4aaf88ac64479e74860b93a5576452ef3cb4cb68ffef -size 10664 diff --git a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.aps2 b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.aps2 new file mode 100644 index 00000000..7cf89baf --- /dev/null +++ b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd31cbd1f5a73e2e315d16835183a44de585fe39b7eb150a4d4de70097a5cdbc +size 638 diff --git a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.h5 b/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.h5 deleted file mode 100644 index 5d400603..00000000 --- a/tests/test_data/awg/TestAPS2/SingleShot/SingleShot-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e4125f49979cef1af9af1aa16d7795f50be4cb39ae02f60aca1a79a31eab3a93 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.aps2 b/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.aps2 new file mode 100644 index 00000000..eded4da5 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c8b7bf6a97cb17eb48dd46c110a9087bb77a0934cf8053dcc9e6b9ad70bcde4 +size 294 diff --git a/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.h5 b/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.h5 deleted file mode 100644 index 0f6b1e0d..00000000 --- a/tests/test_data/awg/TestAPS2/Spec/Spec-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d52de2c3596cc0f61bf8dee2c224d26b5b6bdc378332001d0eea00a15dfe328 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.aps2 b/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.aps2 new file mode 100644 index 00000000..0f81835b --- /dev/null +++ b/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:921a848eed51b9289ca78c382f8bc1efb915f32a7cb2452ba41d0da2a2ab6dde +size 590 diff --git a/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.h5 b/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.h5 deleted file mode 100644 index e89591a9..00000000 --- a/tests/test_data/awg/TestAPS2/Spec/Spec-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4fed627361f76485e09a21c1e72186e64b710ca9a6bf1e71aff1b5cbefebf108 -size 10664 diff --git a/tests/test_data/awg/TestAPS2/T1/T1-APS1.aps2 b/tests/test_data/awg/TestAPS2/T1/T1-APS1.aps2 new file mode 100644 index 00000000..cd52185c --- /dev/null +++ b/tests/test_data/awg/TestAPS2/T1/T1-APS1.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89a2e446a2e8efe6c2b532211dfb6245154566e3a4eaaffedc91172c89f6cdc9 +size 1590 diff --git a/tests/test_data/awg/TestAPS2/T1/T1-APS1.h5 b/tests/test_data/awg/TestAPS2/T1/T1-APS1.h5 deleted file mode 100644 index 5c23cfc1..00000000 --- a/tests/test_data/awg/TestAPS2/T1/T1-APS1.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1ae2feab747be8b5ef6804c3cae154b6099dc30d22c0dd4f62b9bdc121a7beee -size 10664 diff --git a/tests/test_data/awg/TestAPS2/T1/T1-APS2.aps2 b/tests/test_data/awg/TestAPS2/T1/T1-APS2.aps2 new file mode 100644 index 00000000..591b8899 --- /dev/null +++ b/tests/test_data/awg/TestAPS2/T1/T1-APS2.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eab22cfd02f7e5def78a2d83115256554074ea2202ec2406b99e46d4b07921af +size 1342 diff --git a/tests/test_data/awg/TestAPS2/T1/T1-APS2.h5 b/tests/test_data/awg/TestAPS2/T1/T1-APS2.h5 deleted file mode 100644 index 126007b4..00000000 --- a/tests/test_data/awg/TestAPS2/T1/T1-APS2.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:09d114f4c75921bf7aea9db671bbf3618046c1965a4229e405ad0c8d2f7e7805 -size 10664 diff --git a/tests/test_data/multi-align.aps2 b/tests/test_data/multi-align.aps2 new file mode 100644 index 00000000..9d8fd6b2 --- /dev/null +++ b/tests/test_data/multi-align.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be50748c40f8b3bdafc4ff4daa193b607dae69808f0bad20c34b1b31ca32cce +size 5150 diff --git a/tests/test_data/multi-composite.aps2 b/tests/test_data/multi-composite.aps2 new file mode 100644 index 00000000..1499f19a --- /dev/null +++ b/tests/test_data/multi-composite.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e992af922f5470372cd7471c401e39ec89c846f7c56652f3b9ecd622b5a3de20 +size 3614 diff --git a/tests/test_data/multi-operators.aps2 b/tests/test_data/multi-operators.aps2 new file mode 100644 index 00000000..98006e46 --- /dev/null +++ b/tests/test_data/multi-operators.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae9ec04d4585feae8d183dff7cab85c0ba4546b152a1a020421c6cbefc4daf38 +size 8294 diff --git a/tests/test_data/single-ramsey.aps2 b/tests/test_data/single-ramsey.aps2 new file mode 100644 index 00000000..317594ac --- /dev/null +++ b/tests/test_data/single-ramsey.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20f946802a58a5eca8b380c3decbd1efa5b11af7e0218a9aff9b7d7667567361 +size 118358 diff --git a/tests/test_data/single-repeat.aps2 b/tests/test_data/single-repeat.aps2 new file mode 100644 index 00000000..5f927b97 --- /dev/null +++ b/tests/test_data/single-repeat.aps2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79bb0e61d5cbc53767734ea544e111ad5670f1ab4cf9c2945ea7c4e3c82e8be9 +size 4054 diff --git a/tests/test_measure.yml b/tests/test_measure.yml deleted file mode 100644 index fd601cca..00000000 --- a/tests/test_measure.yml +++ /dev/null @@ -1,5 +0,0 @@ -config: - AWGDir: /tmp/awg - KernelDir: /tmp/kern - LogDir: /tmp/alog - \ No newline at end of file diff --git a/tests/test_perf.py b/tests/test_perf.py new file mode 100644 index 00000000..1830e1e2 --- /dev/null +++ b/tests/test_perf.py @@ -0,0 +1,19 @@ +#simple file added for performace testing... + +from QGL import * +import random + +def random_sequence_test(): + N = 1000 + + cl = ChannelLibrary() + q1 = QubitFactory("q1") + + gates = (X90(q1), Y90(q1), X(q1), Y(q1), Id(q1, length=1e-7)) + + seqs = [] + ks = random.choices(range(1,100), k = N) + for k in ks: + seqs.append(random.choices(gates, k=k) + [MEAS(q1)]) + + compile_to_hardware(seqs, 'test/test') diff --git a/utils/convert_h5_to_aps.py b/utils/convert_h5_to_aps.py new file mode 100644 index 00000000..3b0eb8b6 --- /dev/null +++ b/utils/convert_h5_to_aps.py @@ -0,0 +1,106 @@ +import numpy as np +import h5py +import sys +import os.path + +def write_to_aps1(fileName, data): + channelDataFor = np.array([i in data['channelDataFor'] for i in range(1,5)], dtype=np.bool) + try: + with open(fileName, 'wb') as FID: + FID.write(b'APS1') # target hardware + FID.write(np.float32(2.2).tobytes()) # Version + FID.write(channelDataFor.tobytes()) # channelDataFor + FID.write(np.array(data['miniLLRepeat'], dtype=np.bool).tobytes()) # MiniLLRepeat + for name in data['channels'].keys(): + FID.write(np.uint8(data['channels'][name]['isIQMode']).tobytes()) # isIQMode + FID.write(np.uint64(data['channels'][name]['waveformLib'].size).tobytes()) # Length of waveforms + FID.write(data['channels'][name]['waveformLib'].tobytes()) # Waveforms np.int16 + FID.write(np.uint8('linkListData' in data['channels']['chan_1'].keys()).tobytes()) # LL for chan1 + FID.write(np.uint8('linkListData' in data['channels']["chan_3"].keys()).tobytes()) # LL for chan3 + for name in ['chan_1', 'chan_3']: + if 'linkListData' in data['channels'][name].keys(): + FID.write(np.uint64(data['channels'][name]['linkListNumKeys']).tobytes()) # numKeys + FID.write(np.uint64(data['channels'][name]['linkListDataLength']).tobytes()) # numEntries + for key, dataVec in data['channels'][name]['linkListData'].items(): + FID.write(key.ljust(32,"#").encode("utf-8")) # Key 32 byte utf-8 + FID.write(dataVec.tobytes()) + except: + print(f"Warning: could not write aps1 file {fileName}") + +def write_to_aps2(fileName, data): + instructions = data['instructions'] + wfInfo = {} + wfInfo[0] = data['chan1'] + wfInfo[1] = data['chan2'] + + with open(fileName, 'wb') as FID: + FID.write(b'APS2') # target + FID.write(np.float32(data['file_version']).tobytes()) # Version + FID.write(np.float32(data['fw_version']).tobytes()) # minimum firmware version + FID.write(np.uint16(2).tobytes()) # number of channels + # FID.write(np.uint16([1, 2]).tobytes()) # channelDataFor + FID.write(np.uint64(instructions.size).tobytes()) # instructions length + FID.write(instructions.tobytes()) # instructions in uint64 form + + #Create the groups and datasets + for chanct in range(2): + #Write the waveformLib to file + if wfInfo[chanct].size == 0: + #If there are no waveforms, ensure that there is some element + #so that the waveform group gets written to file. + #TODO: Fix this in libaps2 + data = np.array([0], dtype=np.int16) + else: + data = wfInfo[chanct] + FID.write(np.uint64(data.size).tobytes()) # waveform data length for channel + FID.write(data.tobytes()) + +def get_type(fileName): + with h5py.File(fileName, 'r') as FID: + t = FID['/'].attrs['target hardware'] + return t + +def read_aps2_from_h5(fileName): + data = {} + with h5py.File(fileName, 'r') as FID: + data["instrument"] = FID['/'].attrs['target hardware'] + data["file_version"] = FID["/"].attrs["Version"] + data["fw_version"] = FID['/'].attrs['minimum firmware version'] + data["chan1"] = FID['/chan_1/waveforms'].value.flatten() + data["chan2"] = FID['/chan_2/waveforms'].value.flatten() + data["instructions"] = FID['/chan_1/instructions'].value.flatten() + return data + +def read_aps1_from_h5(fileName): + data = {} + with h5py.File(fileName, 'r') as FID: + data["instrument"] = FID['/'].attrs['target hardware'] + data["file_version"] = FID["/"].attrs["Version"] + data["channelDataFor"] = FID["/"].attrs["channelDataFor"] + data["miniLLRepeat"] = FID['/'].attrs['miniLLRepeat'] + channels = list(FID['/'].keys()) + data['channels'] = {} + for channel in channels: + data['channels'][channel] = {'waveformLib': FID[f'/{channel}/waveformLib'].value.flatten()} + data['channels'][channel]['isIQMode'] = FID[f'/{channel}'].attrs['isIQMode'] + if 'linkListData' in list(FID[f'/{channel}'].keys()): + data['channels'][channel]['linkListData'] = {} + for key in FID[f'/{channel}/linkListData'].keys(): + data['channels'][channel]['linkListNumKeys'] = len(FID[f'/{channel}/linkListData'].keys()) + data['channels'][channel]['linkListDataLength'] = FID[f'/{channel}/linkListData'].attrs['length'] + data['channels'][channel]['linkListData'][key] = FID[f'/{channel}/linkListData/{key}'].value.flatten() + return data + +if __name__ == '__main__': + for filename in sys.argv[1:]: + basename, ext = os.path.splitext(filename) + print(f"Converting {basename+'.h5'}") + inst = get_type(basename+'.h5') + if inst == "APS2": + data = read_aps2_from_h5(basename+'.h5') + write_to_aps2(basename+".aps2", data) + if inst == "APS1": + data = read_aps1_from_h5(basename+'.h5') + write_to_aps1(basename+".aps1", data) + + diff --git a/utils/disassemble_aps.py b/utils/disassemble_aps.py new file mode 100755 index 00000000..1b7919c4 --- /dev/null +++ b/utils/disassemble_aps.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +import numpy as np +import sys +import os.path + +from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QAbstractItemView, QPushButton +from PyQt5.QtGui import QIcon, QColor, QFont +from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg +from matplotlib.figure import Figure + +colors = {"WFM": QColor(0,200,0), + "GOTO": QColor(0,100,100), + "MARKER": QColor(150,150,200), + "CUSTOM": QColor(200,65,200), + "WRITEADDR": QColor(245, 105, 65), + "INVALIDATE": QColor(245, 105, 65), + "CALL": QColor(65, 205, 245), + "RET": QColor(65, 205, 245), + "LOADCMP": QColor(245, 225, 65), + "MODULATION": QColor(175, 255, 185)} + +table_font = QFont("Arial", weight=QFont.Bold) + +class MatplotlibWidget(QWidget): + def __init__(self, I, Q, parent=None): + super(MatplotlibWidget, self).__init__(parent) + self.title = 'Waveform' + self.left = 100 + self.top = 100 + self.width = 800 + self.height = 600 + self.setWindowTitle(self.title) + self.setGeometry(self.left, self.top, self.width, self.height) + + self.figure = Figure() + self.canvas = FigureCanvasQTAgg(self.figure) + + self.axis = self.figure.add_subplot(111) + self.axis.plot(I) + self.axis.plot(Q) + self.layout = QVBoxLayout(self) + self.layout.addWidget(self.canvas) + self.setLayout(self.layout) + self.canvas.draw() + self.show() + + +class DisassemblerApp(QWidget): + + COLUMN_COUNT = 7 + + def __init__(self, instructions, waveforms): + super().__init__() + self.title = 'APS2 Disassembled Instructions' + self.left = 100 + self.top = 100 + self.width = 1000 + self.height = 1200 + self.instructions = instructions + self.waveforms = waveforms + self.initUI() + self.plotters = [] + + def initUI(self): + self.setWindowTitle(self.title) + self.setGeometry(self.left, self.top, self.width, self.height) + + self.createTable() + self.layout = QVBoxLayout() + self.layout.addWidget(self.tableWidget) + self.setLayout(self.layout) + + # Show widget + self.show() + + def createTable(self): + # Create table + self.tableWidget = QTableWidget() + self.tableWidget.setRowCount(len(self.instructions)) + self.tableWidget.setColumnCount(self.COLUMN_COUNT) + + for k, instr in enumerate(self.instructions): + fields = str(instr).replace(',','').replace(';', '').split(" ") + if "|" in fields: + fields.remove("|") + if fields[0] in colors: + color = colors[fields[0]] + else: + color = None + for l, f in enumerate(fields): + text = fields[l] + if text == "GOTO": + btn = QPushButton(self.tableWidget) + btn.setText('GOTO') + target_row = int(fields[1].split("=")[1]) + def scroll_to_goto_target(row=target_row, tab=self.tableWidget): + tab.scrollToItem(tab.item(row, 0)) + btn.clicked.connect(scroll_to_goto_target) + btn.setStyleSheet("background-color: #006464; color: white; font-weight: bold; text-align: left;") + self.tableWidget.setCellWidget(k, l, btn) + if text == "WFM" and int(fields[4].split("=")[1])==0: + # Not a TA pair + btn = QPushButton(self.tableWidget) + btn.setText(' WFM') + addr = int(fields[6].split("=")[1]) + count = int(fields[5].split("=")[1]) + def open_plotter(addr=None, I=self.waveforms[0][addr:addr+count], Q=self.waveforms[1][addr:addr+count]): + w = MatplotlibWidget(I,Q) + self.plotters.append(w) + btn.clicked.connect(open_plotter) + btn.setStyleSheet("background-color: #00C800; color: white; font-weight: bold; text-align: left;") + self.tableWidget.setCellWidget(k, l, btn) + else: + item = QTableWidgetItem(text) + item.setFont(table_font) + if color: + item.setBackground(color) + self.tableWidget.setItem(k, l, item) + if l < self.COLUMN_COUNT-1: + for j in range(l+1, self.COLUMN_COUNT): + item = QTableWidgetItem("") + if color: + item.setBackground(color) + self.tableWidget.setItem(k, j, item) + + self.tableWidget.move(0,0) + self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) + +def get_target_hardware(filename): + with open(filename, 'rb') as FID: + target_hw = FID.read(4).decode('utf-8') + return target_hw + +if __name__ == '__main__': + if len(sys.argv) == 2: + filename = sys.argv[1] + try: + hw = get_target_hardware(filename) + if hw == "APS2": + from QGL.drivers.APS2Pattern import read_instructions, read_waveforms + app = QApplication(sys.argv[:1]) + ex = DisassemblerApp(read_instructions(sys.argv[1]), read_waveforms(sys.argv[1])) + sys.exit(app.exec_()) + elif hw == "APS1": + print("APS1 disassmbler not yet implemented") + else: + raise Exception("Unknown hardware target.") + except: + print(f"The supplied file {filename} does not appear to be APS1 or APS2 format.") + + else: + print("Expected single file (.aps1 or .aps2 format) as an argument.") + + + +