Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add errorchecking for QGL2 #222

Merged
merged 8 commits into from
Sep 23, 2019
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*.h5
*.py~
*.py#
*.json~
4 changes: 3 additions & 1 deletion QGL/BasicSequences/Decoupling.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ def CPMG(qubit, numPulses, pulseSpacing, calRepeats=2, showPlot=False):

metafile = compile_to_hardware(seqs, 'CPMG/CPMG',
axis_descriptor=[
delay_descriptor(pulseSpacing * numPulses),
# NOTE: numPulses is often not a numpy array, so cannot multiply by a float.
# But thankfully, np.array(np.array) = np.array so this is always a good move here.
delay_descriptor(pulseSpacing * np.array(numPulses)),
cal_descriptor((qubit,), calRepeats)
])

Expand Down
7 changes: 5 additions & 2 deletions QGL/BasicSequences/helpers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# coding=utf-8

from functools import reduce
from itertools import product
import numpy as np
import operator

from ..PulsePrimitives import Id, X, MEAS
from ..ControlFlow import qwait
from functools import reduce

def create_cal_seqs(qubits, numRepeats, measChans=None, waitcmp=False, delay=None):
"""
Expand Down Expand Up @@ -59,7 +61,8 @@ def delay_descriptor(delays, desired_units="us"):
axis_descriptor = {
'name': 'delay',
'unit': desired_units,
'points': list(scale * delays),
# Make sure delays is a numpy array so can multiply it by a float safely
'points': list(scale * np.array(delays)),
'partition': 1
}
return axis_descriptor
29 changes: 21 additions & 8 deletions QGL/ChannelLibraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,37 +657,50 @@ def set_master(self, master_instrument, trig_channel=None, pulse_length=1e-7):
else:
raise ValueError(f"Could not determine which transmitter to set as master for {master_instrument}:{trig_channel}")

# Used by QGL2, which needs a non-class member function to
# retrieve a Qubit from the CL without accessing the CL directly
def QubitFactory(label):
''' Return a saved qubit channel'''
if channelLib is None:
raise Exception("No channel library initialized")
channelLib.update_channelDict()
cs = [c for c in channelLib.channelDatabase.channels if c.label==label]
# cs = [c for c in channelLib.channelDatabase.channels if c.label==label]
cs = [c for c in channelLib.channelDatabase.channels if c.label==label and isinstance(c, Channels.Qubit)]
# 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 qubit {label} but found {len(cs)} qubits with the same label instead.")
raise Exception(f"Expected to find a single qubit '{label}' but found {len(cs)} qubits with the same label instead.")

def MeasFactory(label):
''' Return a saved measurement channel or create a new one. '''
''' Return a saved measurement channel.'''
if channelLib is None:
raise Exception("No channel library initialized")
channelLib.update_channelDict()
cs = [c for c in channelLib.channelDatabase.channels if c.label==label]
# cs = [c for c in channelLib.channelDatabase.channels if c.label==label]
cs = [c for c in channelLib.channelDatabase.channels if c.label==label and isinstance(c, Channels.Measurement)]
# 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.")
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]
''' Return a saved Marker channel with this label. '''
if channelLib is None:
raise Exception("No channel library initialized")
# cs = [c for c in channelLib.channelDatabase.channels if c.label==label]
cs = [c for c in channelLib.channelDatabase.channels if c.label==label and isinstance(c, Channels.LogicalMarkerChannel)]
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:
raise Exception(f"Expected to find a single marker {label} but found {len(cs)} markers with the same label instead.")
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 channelLib is None:
raise Exception("No channel library initialized")
channelLib.update_channelDict()
if channelLib.connectivityG.has_edge(source, target):
return channelLib.connectivityG[source][target]['channel']
Expand Down
6 changes: 5 additions & 1 deletion QGL/PulseSequencer.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ def __str__(self):
if (n not in self.ignoredStrParams and
n in self.channel.pulse_params and
self.channel.pulse_params[n] != v):
kwvals.append("{0}={1}".format(n, v))
# Hack to make certain printouts prettier...
if callable(v) and v.__module__ == 'QGL.PulseShapes':
kwvals.append("{0}=<{1}>".format(n, v.__name__))
else:
kwvals.append("{0}={1}".format(n, v))
if kwvals:
kwstr = ", " + ", ".join(kwvals)
else:
Expand Down
4 changes: 4 additions & 0 deletions QGL/PulseShapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def gaussian(amp=1, length=0, cutoff=2, sampling_rate=1e9, **params):
A simple gaussian shaped pulse.
cutoff is how many sigma the pulse goes out
'''
if length == 0:
raise ValueError("gaussian() got 0 length")
if sampling_rate == 0:
raise ValueError("gaussian() got 0 sampling_rate")
#Round to how many points we need
numPts = int(np.round(length * sampling_rate))
xPts = np.linspace(-cutoff, cutoff, numPts)
Expand Down
20 changes: 19 additions & 1 deletion QGL/Scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ def schedule(seq):
continue

channels = get_channels(instr, channel_set)
if channels is None:
raise Exception("No channels found from 'get_channels(%s, channel_set)'" % instr)
# find the most advanced counter in the channel set
idx = max(counters.get(ch, 0) for ch in channels)

Expand All @@ -54,8 +56,24 @@ def get_channels(instr, channel_set=None):
return channel_set
elif isinstance(instr, Barrier):
return chanlist
elif isinstance(instr, list):
# This is a bug I think
warn("Supposed instruction is actually a %d item list" % len(instr))

# For debugging, could print these, but this can be verbose
# if len(instr) < 3:
# outstr = ""
# for i in instr:
# outstr += " " + str(i) + "\n"
# if len(outstr) > 160:
# outstr += "...\n"
# break
# print(outstr, end='')

return find_all_channels(instr)
# return None
elif not hasattr(instr, 'channel'):
warn("instruction %s does not have a 'channel' property", instr)
warn("instruction '%s' does not have a 'channel' property" % instr)
return None
elif isinstance(instr.channel, Edge):
return (instr.channel.source, instr.channel.target)
Expand Down