Skip to content

Commit

Permalink
APS3 sequencing and pattern generating.
Browse files Browse the repository at this point in the history
  • Loading branch information
gribeill committed Feb 20, 2018
1 parent 78d23a3 commit 7e8301d
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 26 deletions.
31 changes: 20 additions & 11 deletions QGL/ChannelLibraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(self, file_paths, 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.grace_period = 3.0 if sys.platform == 'darwin' else 1.0
self.last_library_update = datetime.datetime.now()

def on_modified(self, event):
Expand All @@ -71,7 +71,7 @@ def on_modified(self, event):
# 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
"""
Expand All @@ -89,7 +89,7 @@ def on_modified(self, event):
class LibraryFileWatcher(object):
def __init__(self, main_path, callback):
super(LibraryFileWatcher, self).__init__()

self.main_path = os.path.normpath(main_path)
self.callback = callback

Expand Down Expand Up @@ -133,9 +133,9 @@ class ChannelLibrary(Atom):
'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
"""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)

Expand All @@ -152,7 +152,7 @@ def __init__(self, library_file=None, blank=False, channelDict={}, **kwargs):
# Update the global reference
global channelLib
if channelLib:
# Don't let the
# Don't let the
channelLib.fileWatcher = None
channelLib = self

Expand Down Expand Up @@ -259,7 +259,7 @@ def load_from_library(self, return_only=False):
marker_lens[params["label"]] = marker["length"]
channel_dict[params["label"]] = params
if "master" in instr.keys() and instr["master"]:
if instr['type'] != 'TDM':
if instr['type'] not in ('APS3', 'TDM'):
slave_chan = instr["slave_trig"] if "slave_trig" in instr.keys() else "slave"
master_awgs.append(name + "-" + slave_chan)
else:
Expand All @@ -279,7 +279,7 @@ def load_from_library(self, return_only=False):
# 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':
elif len(master_awgs) == 1 and instr_dict[master_awgs[0].split('-')[0]]['type'] not in ('TDM', 'APS3'):
params = {}
params["label"] = "slave_trig"
params["phys_chan"] = master_awgs[0]
Expand Down Expand Up @@ -330,16 +330,25 @@ def load_from_library(self, return_only=False):
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)
params["trig_chan"] = "digTrig-" + qubit["measure"]["trigger"]
params["trig_chan"] = "digTrig-" + qubit["measure"]["trigger"]
if instr_dict[meas_instr]["type"] != "APS3":
params["meas_type"] = "autodyne"
else:
params["meas_type"] = "heterodyne"
#frequency difference for DDS phase shift between nco and heterodyne LO
gen_freq = instr_dict[qubit["measure"]["generator"]]["frequency"]
dds_freq = instr_dict[meas_instr]["dac_clock"] + instr_dict[meas_instr]["nco_frequency"]
params["heterodyne_frequency"] = gen_freq - dds_freq
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:
Expand Down Expand Up @@ -382,7 +391,6 @@ def load_from_library(self, return_only=False):
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 = {}
Expand Down Expand Up @@ -430,6 +438,7 @@ def load_from_library(self, return_only=False):
for chan in channel_dict.values():
for param in self.specialParams:
if hasattr(chan, param) and getattr(chan, param) is not None:
print(chan, param)
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))
Expand Down
3 changes: 2 additions & 1 deletion QGL/Channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,14 @@ class Measurement(LogicalChannel):
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(
meas_type = Enum('autodyne', 'homodyne', 'heterodyne').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')
heterodyne_frequency = Float(0.0).tag(desc='Use to correct for phase shifts due to heterodyning.')
pulse_params = Dict(default={'length': 100e-9,
'amp': 1.0,
'shape_fun': PulseShapes.tanh,
Expand Down
25 changes: 21 additions & 4 deletions QGL/Compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from . import Channels
from . import ChannelLibraries
from . import PulseShapes
from .PulsePrimitives import Id
from .PulsePrimitives import Id, MEAS
from .PulseSequencer import Pulse, PulseBlock, CompositePulse
from . import ControlFlow
from . import BlockLabel
Expand Down Expand Up @@ -365,7 +365,7 @@ def compile_to_hardware(seqs,
num_measurements = count_measurements(wireSeqs)
wire_measurements = count_measurements_per_wire(wireSeqs)

# map logical to physical channels, physWires is a list of
# map logical to physical channels, physWires is a list of
# PhysicalQuadratureChannels and PhysicalMarkerChannels
# for the APS, the naming convention is:
# ASPName-12, or APSName-12m1
Expand All @@ -390,7 +390,7 @@ def compile_to_hardware(seqs,
old_wire_names[wire] = wire.label
old_wire_instrs[wire] = wire.instrument
wire.instrument = wire.label
wire.label = chan_name
wire.label = chan_name
files[inst_name] = {}

# construct channel delay map
Expand Down Expand Up @@ -463,7 +463,6 @@ def compile_to_hardware(seqs,
# Return the filenames we wrote
return metafilepath


def compile_sequences(seqs, channels=set()):
'''
Main function to convert sequences to miniLL's and waveform libraries.
Expand Down Expand Up @@ -491,6 +490,24 @@ def compile_sequences(seqs, channels=set()):
wires = compile_sequence(seq, channels)
for chan in wireSeqs.keys():
wireSeqs[chan].append(wires[chan])

for chan, seqs in wireSeqs.items():
## If we are using an APS3 with heterodyne readout, sum up the delays before the
## measurement pulse and apply a phase shift to correct for the
if isinstance(chan, Channels.Measurement) and chan.meas_type == "heterodyne":
qubit_label = chan.label.split('-')[1]
qubit = ChannelLibraries.QubitFactory(qubit_label)
for seq in seqs:
meas_idx = [idx for idx, p in enumerate(seq) if getattr(p, "label", None) == "MEAS"]
if len(meas_idx) != 1:
raise NotImplementedError("Unable to handle DDS sequences with more than one measurement.")
delay = sum([p.length for p in seq[:meas_idx[0]]])
old_meas = seq[meas_idx[0]]
phase = old_meas.phase + delay * chan.heterodyne_frequency
seq[meas_idx[0]] = MEAS(qubit, amp=old_meas.amp, phase = phase)



#Print a message so for the experiment we know how many sequences there are
print('Compiled {} sequences.'.format(len(seqs) - len(subroutines)))

Expand Down
16 changes: 11 additions & 5 deletions QGL/PulsePrimitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,26 +717,32 @@ def CNOT_simple(source, target, **kwargs):
def CNOT(source, target, **kwargs):
cnot_impl = globals()[config.cnot_implementation]
return cnot_impl(source, target, **kwargs)

## Measurement operators
@_memoize
#@_memoize
def MEAS(qubit, **kwargs):
'''
MEAS(q1) measures a qubit. Applies to the pulse with the label M-q1
'''
channelName = "M-" + qubit.label
measChan = ChannelLibraries.MeasFactory(channelName)
params = overrideDefaults(measChan, kwargs)
if measChan.meas_type == 'autodyne':
if measChan.meas_type in ('autodyne', 'heterodyne'):
params['frequency'] = measChan.autodyne_freq
params['baseShape'] = params.pop('shape_fun')
params['shape_fun'] = PulseShapes.autodyne
amp = params.pop('amp')
ignoredStrParams = ['phase', 'frameChange']
#ignoredStrParams = ['phase', 'frameChange']
ignoredStrParams = ['frameChange']
if 'amp' not in kwargs:
ignoredStrParams.append('amp')
if 'phase' not in kwargs:
phase = 0.0
ignoredStrParams.append('phase')
else:
phase = kwargs['phase']
meas_label = "MEAS_no_trig" if 'dig_trig' in kwargs and not kwargs['dig_trig'] else "MEAS"
return Pulse(meas_label, measChan, params, amp, 0.0, 0.0, ignoredStrParams)
return Pulse(meas_label, measChan, params, amp, phase, 0.0, ignoredStrParams)


#MEAS and ring-down time on one qubit, echo on every other
Expand Down
9 changes: 4 additions & 5 deletions QGL/PulseSequencePlotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def plot_pulse_files(metafile, time=False):
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

with open(metafile, 'r') as FID:
meta_info = json.load(FID)
fileNames = []
Expand Down Expand Up @@ -172,12 +172,11 @@ def extract_waveforms(fileNames, nameDecorator='', time=False):
translator = resolve_translator(fileName, translators)
wfs = translator.read_sequence_file(fileName)
sample_time = 1.0/translator.SAMPLING_RATE if time else 1

for (k, seqs) in sorted(wfs.items()):
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)] = {}
Expand Down Expand Up @@ -205,7 +204,7 @@ def plot_pulse_files_compare(metafile1, metafile2, time=False):

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):
Expand All @@ -216,7 +215,7 @@ def plot_pulse_files_compare(metafile1, metafile2, time=False):

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):
Expand Down

0 comments on commit 7e8301d

Please sign in to comment.