From 4f02c919334ae7efe2e8fe75e1baa92c9b4b1bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Tue, 29 Oct 2019 16:41:42 -0400 Subject: [PATCH 01/25] :bug: cal_db print --- QGL/ChannelLibraries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index e0f1f8fa..678b6822 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -150,7 +150,7 @@ def ls(self): def cal_ls(self): ''' List of auspex.pulse_calibration results ''' caldb = bbndb.calibration.Calibration - c = self.session.query(caldb.sample_id, caldb.name, caldb.value, caldb.date).order_by(-Channels.ChannelDatabase.id).all() + c = self.session.query(caldb.id, caldb.sample_id, caldb.name, caldb.value, caldb.date).order_by(-caldb.id).all() table_code = "" for i, (id, sample_id, name, value, time) in enumerate(c): d,t = str(time).split() From d90a333303ca6195359d8ddeff7d2b7f284ea5fc Mon Sep 17 00:00:00 2001 From: Spencer Fallek Date: Fri, 1 Nov 2019 12:31:11 -0400 Subject: [PATCH 02/25] add VRAM max address --- QGL/drivers/APS2Pattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index d6e3d10c..6d9da1ee 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -47,7 +47,7 @@ MAX_NUM_INSTRUCTIONS = 2**26 MAX_REPEAT_COUNT = 2**16 - 1 MAX_TRIGGER_COUNT = 2**32 - 1 - +MAX_VRAM_ADDRESS = 2**12-1 MODULATION_CLOCK = 300e6 # instruction encodings From ec3c6253f33313a4fabdc51697130a389c5eaf77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Mon, 4 Nov 2019 12:14:28 -0500 Subject: [PATCH 03/25] Fix isTimeAmp check shapeParams['shape_fun'] is typically a string --- QGL/PulseSequencer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/QGL/PulseSequencer.py b/QGL/PulseSequencer.py index d19027f5..d70069b7 100644 --- a/QGL/PulseSequencer.py +++ b/QGL/PulseSequencer.py @@ -47,7 +47,11 @@ def __new__(cls, label, channel, shapeParams, amp=1.0, phase=0, frameChange=0, i for param in requiredParams: if param not in shapeParams.keys(): raise NameError("shapeParams must include {0}".format(param)) - isTimeAmp = (shapeParams['shape_fun'] == PulseShapes.constant) + if isinstance(shapeParams['shape_fun'],str): + shape = getattr(PulseShapes, shapeParams['shape_fun']) + else: + shape = shapeParams['shape_fun'] + isTimeAmp = (shape == PulseShapes.constant) isZero = (amp == 0) return super(cls, Pulse).__new__(cls, label, channel, shapeParams['length'], amp, phase, From 09217129dc1e20a172543ebcc399b044c2c588ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Mon, 4 Nov 2019 12:14:28 -0500 Subject: [PATCH 04/25] Fix isTimeAmp check shapeParams['shape_fun'] is typically a string --- QGL/PulseSequencer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/QGL/PulseSequencer.py b/QGL/PulseSequencer.py index d19027f5..d70069b7 100644 --- a/QGL/PulseSequencer.py +++ b/QGL/PulseSequencer.py @@ -47,7 +47,11 @@ def __new__(cls, label, channel, shapeParams, amp=1.0, phase=0, frameChange=0, i for param in requiredParams: if param not in shapeParams.keys(): raise NameError("shapeParams must include {0}".format(param)) - isTimeAmp = (shapeParams['shape_fun'] == PulseShapes.constant) + if isinstance(shapeParams['shape_fun'],str): + shape = getattr(PulseShapes, shapeParams['shape_fun']) + else: + shape = shapeParams['shape_fun'] + isTimeAmp = (shape == PulseShapes.constant) isZero = (amp == 0) return super(cls, Pulse).__new__(cls, label, channel, shapeParams['length'], amp, phase, From 737cf4e7cda084cb75c11a657c4f678757a5b322 Mon Sep 17 00:00:00 2001 From: Graham Rowlands Date: Thu, 7 Nov 2019 16:43:27 -0500 Subject: [PATCH 05/25] Generic new_transceiver function for dummy/aps3 noodling --- QGL/ChannelLibraries.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index cabfb3a3..f7393b9c 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -478,6 +478,42 @@ def new_APS2_rack(self, label, ip_addresses, tdm_ip=None, **kwargs): self.add_and_update_dict(this_transceiver) return this_transceiver + @check_for_duplicates + def new_transceiver(self, model, label, address, numtx=1, numrx=1, nummark=4, record_length = 1024, **kwargs): + translator = model+"Pattern" + stream_sel = model+"StreamSelector" + + chans = [] + for i in range(numtx): + chan = Channels.PhysicalQuadratureChannel(label=f"{label}-Tx{i+1}-1", instrument=label, channel=i, translator=translator, channel_db=self.channelDatabase) + chans.append(chan) + for i in range(nummark): + chan = Channels.PhysicalMarkerChannel(label=f"{label}-Tx{i+1}-M", channel=i, instrument=label, translator=translator, channel_db=self.channelDatabase) + chans.append(chan) + + transmitter = Channels.Transmitter(label=f"{label}-Tx", model=model, address=address, channels=chans, channel_db=self.channelDatabase) + transmitter.trigger_source = "external" + transmitter.address = address + + chans = [] + for i in range(numrx): + chan = Channels.ReceiverChannel(label=f"RecvChan-{label}-{i+1}", channel=i, channel_db=self.channelDatabase) + chans.append(chan) + + receiver = Channels.Receiver(label=f"{label}-Rx", model=model, address=address, channels=chans, record_length=record_length, channel_db=self.channelDatabase) + receiver.trigger_source = "external" + receiver.stream_types = "raw" + receiver.address = address + receiver.stream_sel = stream_sel + + transceiver = Channels.Transceiver(label=label, address=address, model=model, transmitters=[transmitter], receivers = [receiver], initialize_separately=False, channel_db=self.channelDatabase) + transmitter.transceiver = transceiver + receiver.transceiver = transceiver + + self.add_and_update_dict(transceiver) + return transceiver + + @check_for_duplicates def new_X6(self, label, address, dsp_channel=0, record_length=1024, **kwargs): From c0b89569626b392bb423ee2fa6672d7a3f7b75b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Fri, 8 Nov 2019 15:35:05 -0500 Subject: [PATCH 06/25] Move cal_ls to auspex cal_ls doesn't belong to ChannelLibraries. Moved to auspex --- QGL/ChannelLibraries.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index cabfb3a3..c7a29076 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -147,17 +147,6 @@ def ls(self): table_code += f"{id}{y}{d}{t}{label}{notes}" display(HTML(f"{table_code}
idYearDateTimeNameNotes
")) - def cal_ls(self): - ''' List of auspex.pulse_calibration results ''' - caldb = bbndb.calibration.Calibration - c = self.session.query(caldb.id, caldb.sample_id, caldb.name, caldb.value, caldb.date).order_by(-caldb.id).all() - table_code = "" - for i, (sample_id, name, value, time) in enumerate(c): - d,t = str(time).split() - sample = self.session.query(bbndb.calibration.Sample).filter_by(id=sample_id).first() - table_code += f"{id}{d}{t.split('.')[0]}{sample.name}{name}{round(value,9)}" - display(HTML(f"{table_code}
idDateTimeSampleNameValue
")) - 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: From f121681f26c459b89095f7d9e0e0c63b240b0057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Wed, 13 Nov 2019 11:47:18 -0500 Subject: [PATCH 07/25] Fix length SSB wfs --- QGL/drivers/APSPattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/drivers/APSPattern.py b/QGL/drivers/APSPattern.py index c6a1260f..865537b8 100644 --- a/QGL/drivers/APSPattern.py +++ b/QGL/drivers/APSPattern.py @@ -151,7 +151,7 @@ def build_waveforms(seqs, shapeLib): shape = np.exp(1j * wf.phase) * wf.amp * shapeLib[wf.key] if wf.frequency != 0 and wf.amp != 0: shape *= np.exp( - -1j * 2 * np.pi * wf.frequency * np.arange(wf.length) / + -1j * 2 * np.pi * wf.frequency * np.arange(len(shape)) / SAMPLING_RATE) #minus from negative frequency qubits wfLib[wf_sig(wf)] = shape return wfLib From 1bbe3c0a7ea24e3e1d0bade9f7176c4f3469fbbd Mon Sep 17 00:00:00 2001 From: Brian Donovan Date: Wed, 28 Nov 2018 12:52:58 -0500 Subject: [PATCH 08/25] Merge conflict --- QGL/drivers/APS2Pattern.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index 6d9da1ee..61c6e597 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -49,6 +49,7 @@ MAX_TRIGGER_COUNT = 2**32 - 1 MAX_VRAM_ADDRESS = 2**12-1 MODULATION_CLOCK = 300e6 +NUM_NCO = 4 # instruction encodings WFM = 0x0 @@ -581,13 +582,19 @@ def to_instruction(self, write_flag=True, label=None): MODULATOR_OP_OFFSET = 44 NCO_SELECT_OP_OFFSET = 40 + 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) | ( - self.nco_select << NCO_SELECT_OP_OFFSET) + (nco_select_bits) << NCO_SELECT_OP_OFFSET) if self.instruction == "MODULATE": #zero-indexed quad count payload |= np.uint32(self.length / ADDRESS_UNIT - 1) @@ -615,9 +622,9 @@ 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) > 2: - raise Exception("Max 2 frequencies on the same channel allowed.") - no_freq_cmds = np.all(np.less(np.abs(freqs), 1e-8)) + if len(freqs) > NUM_NCO: + raise Exception("Max {} frequencies on the same channel allowed.".format(NUM_NCO)) + no_freq_cmds = np.allclose(freqs, 0) phases = [entry.phase for entry in filter(lambda s: isinstance(s,Compiler.Waveform), seq)] 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)] @@ -1135,12 +1142,13 @@ def start_new_seq(): instructions = np.frombuffer(FID.read(8*inst_len), dtype=np.uint64) wf_lib = {} - for i in range(num_chans): - wf_len = struct.unpack(' Date: Wed, 28 Nov 2018 13:05:55 -0500 Subject: [PATCH 09/25] Reset 4 NCOs --- QGL/drivers/APS2Pattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index 61c6e597..23c41f97 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -648,7 +648,7 @@ def inject_modulation_cmds(seqs): #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", 0x3)) + mod_seq.append(ModulationCommand("RESET_PHASE", 0xF)) for nco_ind, freq in enumerate(freqs): mod_seq.append( ModulationCommand("SET_FREQ", nco_ind + 1, frequency = -freq) ) elif isinstance(entry, ControlFlow.Return): From 6990088cbef5120d96952ad0d076922b624c856e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Fri, 15 Nov 2019 13:16:51 -0500 Subject: [PATCH 10/25] Restore aps2 format --- QGL/drivers/APS2Pattern.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index 23c41f97..39210163 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -1142,13 +1142,10 @@ def start_new_seq(): instructions = np.frombuffer(FID.read(8*inst_len), dtype=np.uint64) wf_lib = {} - wf_lib['ch1'] = ( - 1.0 / - MAX_WAVEFORM_VALUE) * FID['/chan_1/waveforms'].value.flatten() - wf_lib['ch2'] = ( - 1.0 / - MAX_WAVEFORM_VALUE) * FID['/chan_2/waveforms'].value.flatten() - instructions = FID['/chan_1/instructions'].value.flatten() + for i in range(num_chans): + wf_len = struct.unpack(' Date: Mon, 18 Nov 2019 10:56:46 -0500 Subject: [PATCH 11/25] Load and cmp two chan. libraries --- QGL/ChannelLibraries.py | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index c7a29076..48e2c2e3 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -262,6 +262,59 @@ def spike_at(f): figs.append(Figure(marks=lines+[labels], axes=[ax, ay], title=f"{ss} Frequency Plan")) return HBox(figs) + def diff(self, name1, name2, index1=1, index2=1): + ''' + Compare 2 channel library versions. Print the difference between 2 libraries, including parameter values and channel allocations. It requires both versions to be saved in the same sqlite database. + Args + name1: name of first version to compare + name2: name of second version to compare + index1, index2: by default, loading the most recent instances for the given names. Specifying index1/2 = 2 will select the second most recent instance etc.""" + ''' + cdb = Channels.ChannelDatabase + db1 = self.session.query(cdb).filter(cdb.label==name1)[-1*index1] + db2 = self.session.query(cdb).filter(cdb.label==name2)[-1*index2] + copied_db1 = bbndb.deepcopy_sqla_object(db1) + copied_db2 = bbndb.deepcopy_sqla_object(db2) + dict_1 = {c.label: c for c in copied_db1.channels} + dict_2 = {c.label: c for c in copied_db2.channels} + + def iter_diff(value_iter1, value_iter2, ct, label=''): + for key, key2 in zip(value_iter1, value_iter2): + if key in ['_sa_instance_state', 'channel_db']: + continue + if isinstance(value_iter1, dict): + cmp1 = value_iter1[key] + cmp2 = value_iter2[key] + if label in value_iter1: + label = value_iter1['label'] + elif isinstance(value_iter1, list): + cmp1 = key + cmp2 = key2 + else: + cmp1 = getattr(value_iter1, key) + cmp2 = getattr(value_iter2, key) + if (cmp1 == None) ^ (cmp2 == None): + print(f'Difference found {label} {key} : 1st {cmp1} 2nd: {cmp2}') + continue + if (cmp1 == None) or (cmp2 == None) or ((isinstance(cmp1, dict) or isinstance(cmp1, list)) and len(cmp1) == 0): + continue + if isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + cmp1 = cmp1.__dict__ + cmp2 = cmp2.__dict__ + if isinstance(cmp1, dict) or isinstance(cmp1, list) or isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations + ct+=1 + iter_diff(cmp1, cmp2, ct, label=label) + break + if cmp1 != cmp2: + print(f'Difference found {label} {key} : 1st {cmp1} 2nd: {cmp2}') + + for chan, value in dict_1.items(): + this_dict = value.__dict__ + ct = 0 + iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) + return db1, db2, copied_db1, copied_db2 + def receivers(self): return self.ent_by_type(Channels.Receiver) @@ -274,6 +327,9 @@ def transceivers(self): def qubits(self): return self.ent_by_type(Channels.Qubit) + def edges(self): + return self.ent_by_type(Channels.Edge) + def meas(self): return self.ent_by_type(Channels.Measurement) From b968726dc90bcba4d1dd29b3bfa7cc1cf2544138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Mon, 18 Nov 2019 10:59:46 -0500 Subject: [PATCH 12/25] No db return needed --- QGL/ChannelLibraries.py | 1 - 1 file changed, 1 deletion(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index 48e2c2e3..2b1843aa 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -313,7 +313,6 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): this_dict = value.__dict__ ct = 0 iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) - return db1, db2, copied_db1, copied_db2 def receivers(self): return self.ent_by_type(Channels.Receiver) From a4c355884b2a5eb842de8226f5736052ee8c0b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Tue, 19 Nov 2019 09:57:55 -0500 Subject: [PATCH 13/25] display diff as table --- QGL/ChannelLibraries.py | 66 ++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index 2b1843aa..faac801c 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -279,40 +279,44 @@ def diff(self, name1, name2, index1=1, index2=1): dict_2 = {c.label: c for c in copied_db2.channels} def iter_diff(value_iter1, value_iter2, ct, label=''): - for key, key2 in zip(value_iter1, value_iter2): - if key in ['_sa_instance_state', 'channel_db']: - continue - if isinstance(value_iter1, dict): - cmp1 = value_iter1[key] - cmp2 = value_iter2[key] - if label in value_iter1: - label = value_iter1['label'] - elif isinstance(value_iter1, list): - cmp1 = key - cmp2 = key2 - else: - cmp1 = getattr(value_iter1, key) - cmp2 = getattr(value_iter2, key) - if (cmp1 == None) ^ (cmp2 == None): - print(f'Difference found {label} {key} : 1st {cmp1} 2nd: {cmp2}') - continue - if (cmp1 == None) or (cmp2 == None) or ((isinstance(cmp1, dict) or isinstance(cmp1, list)) and len(cmp1) == 0): - continue - if isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): - cmp1 = cmp1.__dict__ - cmp2 = cmp2.__dict__ - if isinstance(cmp1, dict) or isinstance(cmp1, list) or isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): - if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations - ct+=1 - iter_diff(cmp1, cmp2, ct, label=label) - break - if cmp1 != cmp2: - print(f'Difference found {label} {key} : 1st {cmp1} 2nd: {cmp2}') - + table_code = '' + for key, key2 in zip(value_iter1, value_iter2): + if key in ['_sa_instance_state', 'channel_db']: + continue + if isinstance(value_iter1, dict): + cmp1 = value_iter1[key] + cmp2 = value_iter2[key] + if label in value_iter1: + label = value_iter1['label'] + elif isinstance(value_iter1, list): + cmp1 = key + cmp2 = key2 + else: + cmp1 = getattr(value_iter1, key) + cmp2 = getattr(value_iter2, key) + if (cmp1 == None) ^ (cmp2 == None): + table_code += f"{label}{key}{cmp1}{cmp2}" + continue + if (cmp1 == None) or (cmp2 == None) or ((isinstance(cmp1, dict) or isinstance(cmp1, list)) and len(cmp1) == 0): + continue + if isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + cmp1 = cmp1.__dict__ + cmp2 = cmp2.__dict__ + if isinstance(cmp1, dict) or isinstance(cmp1, list) or isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations + ct+=1 + iter_diff(cmp1, cmp2, ct, label=label) + break + if cmp1 != cmp2: + table_code += f"{label}{key}{cmp1}{cmp2}" + return table_code + + table_code = '' for chan, value in dict_1.items(): this_dict = value.__dict__ ct = 0 - iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) + table_code += iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) + display(HTML(f"{table_code}
ObjectParameter{name1}{name2}
")) def receivers(self): return self.ent_by_type(Channels.Receiver) From 6b6781731422b1064f1c7e417e0d418d733bb016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Tue, 19 Nov 2019 10:06:04 -0500 Subject: [PATCH 14/25] Fix table_code accumulation --- QGL/ChannelLibraries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index faac801c..785e5aff 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -305,7 +305,7 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): if isinstance(cmp1, dict) or isinstance(cmp1, list) or isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations ct+=1 - iter_diff(cmp1, cmp2, ct, label=label) + table_code += iter_diff(cmp1, cmp2, ct, label=label) break if cmp1 != cmp2: table_code += f"{label}{key}{cmp1}{cmp2}" From dfdca261d6cf50ef4ccd51485f5b3816ad74c200 Mon Sep 17 00:00:00 2001 From: Spencer Fallek <38664981+sfallek1@users.noreply.github.com> Date: Tue, 26 Nov 2019 13:33:33 -0500 Subject: [PATCH 15/25] update MAX_VRAM_ADDRESS --- QGL/drivers/APS2Pattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QGL/drivers/APS2Pattern.py b/QGL/drivers/APS2Pattern.py index 6d9da1ee..6b4e9af4 100644 --- a/QGL/drivers/APS2Pattern.py +++ b/QGL/drivers/APS2Pattern.py @@ -47,7 +47,7 @@ MAX_NUM_INSTRUCTIONS = 2**26 MAX_REPEAT_COUNT = 2**16 - 1 MAX_TRIGGER_COUNT = 2**32 - 1 -MAX_VRAM_ADDRESS = 2**12-1 +MAX_VRAM_ADDRESS = 2**(12-2)-1 MODULATION_CLOCK = 300e6 # instruction encodings From 2ac324af6537c93cf1249fc532a2e2807e785b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Tue, 10 Dec 2019 13:00:32 -0500 Subject: [PATCH 16/25] Include instruments in diff And count db versions starting from most recent --- QGL/ChannelLibraries.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index 785e5aff..a781e260 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -271,13 +271,12 @@ def diff(self, name1, name2, index1=1, index2=1): index1, index2: by default, loading the most recent instances for the given names. Specifying index1/2 = 2 will select the second most recent instance etc.""" ''' cdb = Channels.ChannelDatabase - db1 = self.session.query(cdb).filter(cdb.label==name1)[-1*index1] - db2 = self.session.query(cdb).filter(cdb.label==name2)[-1*index2] + db1 = self.session.query(cdb).filter(cdb.label==name1).order_by(cdb.time.desc())[-1*index1] + db2 = self.session.query(cdb).filter(cdb.label==name2).order_by(cdb.time.desc())[-1*index2] copied_db1 = bbndb.deepcopy_sqla_object(db1) copied_db2 = bbndb.deepcopy_sqla_object(db2) - dict_1 = {c.label: c for c in copied_db1.channels} - dict_2 = {c.label: c for c in copied_db2.channels} - + dict_1 = {c.label: c for c in copied_db1.channels + copied_db1.all_instruments()} + dict_2 = {c.label: c for c in copied_db2.channels + copied_db2.all_instruments()} def iter_diff(value_iter1, value_iter2, ct, label=''): table_code = '' for key, key2 in zip(value_iter1, value_iter2): @@ -299,10 +298,10 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): continue if (cmp1 == None) or (cmp2 == None) or ((isinstance(cmp1, dict) or isinstance(cmp1, list)) and len(cmp1) == 0): continue - if isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + if isinstance(cmp1, (bbndb.qgl.DatabaseItem, bbndb.qgl.Channel, bbndb.qgl.Instrument)): cmp1 = cmp1.__dict__ cmp2 = cmp2.__dict__ - if isinstance(cmp1, dict) or isinstance(cmp1, list) or isinstance(cmp1, bbndb.qgl.DatabaseItem) or isinstance(cmp1, bbndb.qgl.Channel): + if isinstance(cmp1, (dict, list, bbndb.qgl.DatabaseItem, bbndb.qgl.Channel, bbndb.qgl.Instrument)): if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations ct+=1 table_code += iter_diff(cmp1, cmp2, ct, label=label) From 5cf3604c9eddca698f091c773237f80454cb8462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Fri, 13 Dec 2019 13:03:48 -0500 Subject: [PATCH 17/25] Fix loop in cl.diff --- QGL/ChannelLibraries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index a781e260..077eac6d 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -289,7 +289,7 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): label = value_iter1['label'] elif isinstance(value_iter1, list): cmp1 = key - cmp2 = key2 + cmp2 = key2 #TODO fix. why would they be in any order? else: cmp1 = getattr(value_iter1, key) cmp2 = getattr(value_iter2, key) @@ -305,7 +305,7 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): if ct<1: # up to 2 recursion levels for now, to avoid infinite loops for bidirectional relations ct+=1 table_code += iter_diff(cmp1, cmp2, ct, label=label) - break + continue if cmp1 != cmp2: table_code += f"{label}{key}{cmp1}{cmp2}" return table_code From 6a6aaef17c44f0104a56e3d6ce33be1f768c9839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Fri, 13 Dec 2019 14:09:46 -0500 Subject: [PATCH 18/25] Fix latest instance given name Desc -> Asc. order if we count from the end --- QGL/ChannelLibraries.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index ed0289dc..bd35deb7 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -271,8 +271,8 @@ def diff(self, name1, name2, index1=1, index2=1): index1, index2: by default, loading the most recent instances for the given names. Specifying index1/2 = 2 will select the second most recent instance etc.""" ''' cdb = Channels.ChannelDatabase - db1 = self.session.query(cdb).filter(cdb.label==name1).order_by(cdb.time.desc())[-1*index1] - db2 = self.session.query(cdb).filter(cdb.label==name2).order_by(cdb.time.desc())[-1*index2] + db1 = self.session.query(cdb).filter(cdb.label==name1).order_by(cdb.time.asc())[-1*index1] + db2 = self.session.query(cdb).filter(cdb.label==name2).order_by(cdb.time.asc())[-1*index2] copied_db1 = bbndb.deepcopy_sqla_object(db1) copied_db2 = bbndb.deepcopy_sqla_object(db2) dict_1 = {c.label: c for c in copied_db1.channels + copied_db1.all_instruments()} @@ -342,7 +342,7 @@ def markers(self): 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() + items = self.session.query(cdb).filter(cdb.label==name).order_by(cdb.time.asc()).all() self.load_obj(items[-index]) @check_session_dirty From 5f287eaadb43b3f04011c07016a82e932c1bf769 Mon Sep 17 00:00:00 2001 From: Billy Date: Tue, 17 Dec 2019 11:40:47 -0500 Subject: [PATCH 19/25] Leakage RB --- QGL/BasicSequences/RB.py | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/QGL/BasicSequences/RB.py b/QGL/BasicSequences/RB.py index 11285889..6163e700 100644 --- a/QGL/BasicSequences/RB.py +++ b/QGL/BasicSequences/RB.py @@ -86,6 +86,56 @@ def SingleQubitRB(qubit, seqs, purity=False, showPlot=False, add_cals=True): plot_pulse_files(metafile) return metafile +def SingleQubitLeakageRB(qubit, seqs, pi2args, showPlot=False): + """Single qubit randomized benchmarking using 90 and 180 generators to + measure leakage outside the qubit subspace. + See https://journals.aps.org/prl/supplemental/10.1103/PhysRevLett.123.120502/Rol_SOM.pdf + for description of algorithm. + + Parameters + ---------- + qubit : logical channel to implement sequence (LogicalChannel) + seqs : list of lists of Clifford group integers + pi2args: arguments passed to the X90 gate for the 1 <-> 2 transition during calibration + showPlot : whether to plot (boolean) + """ + + seqsBis = [] + for seq in seqs: + combined_seq = reduce(operator.add, [clifford_seq(c, qubit) for c in seq]) + + # Append sequence with tomography ids and measurement + seqsBis.append(combined_seq + [Id(qubit), Id(qubit), MEAS(qubit)]) + + # Append sequence with tomography pulses and measurement + seqsBis.append(combined_seq + [X90(qubit), X90(qubit), MEAS(qubit)]) + + # Add the calibration sequences + seqsBis.append([Id(qubit), Id(qubit), Id(qubit), Id(qubit), MEAS(qubit)]) + seqsBis.append([X90(qubit), X90(qubit), Id(qubit), Id(qubit), MEAS(qubit)]) + seqsBis.append([X90(qubit), X90(qubit), X90(qubit, **pi2args), X90(qubit, **pi2args), MEAS(qubit)]) + + axis_descriptor = [ + { + 'name': 'length', + 'unit': None, + 'points': [len(s) for s in seqs for i in range(2)], + 'partition': 1 + }, + { + 'name': 'calibration', + 'unit': 'state', + 'partition': 2, + 'points': ['0', '1', '2'] + }] + + metafile = compile_to_hardware(seqsBis, 'RB/LRB', axis_descriptor = axis_descriptor, extra_meta = {'sequences':seqs}) + + if showPlot: + plot_pulse_files(metafile) + return metafile + + def TwoQubitRB(q1, q2, seqs, showPlot=False, suffix="", add_cals=True): """Two qubit randomized benchmarking using 90 and 180 single qubit generators and ZX90 @@ -124,6 +174,53 @@ def TwoQubitRB(q1, q2, seqs, showPlot=False, suffix="", add_cals=True): plot_pulse_files(metafile) return metafile +def TwoQubitLeakageRB(q1, q2, meas_qubit, seqs, pi2args, showPlot=False): + """Two qubit randomized benchmarking using 90 and 180 single qubit generators and ZX90 to + measure leakage outside the qubit subspace. + See https://journals.aps.org/prl/supplemental/10.1103/PhysRevLett.123.120502/Rol_SOM.pdf + for description of algorithm. + Parameters + ---------- + qubit : logical channel to implement sequence (LogicalChannel) + seqs : list of lists of Clifford group integers + showPlot : whether to plot (boolean) + suffix : suffix to apply to sequence file names + """ + seqsBis = [] + for seq in seqs: + combined_seq = reduce(operator.add, [clifford_seq(c, q2, q1) for c in seq]) + + # Append sequence with tomography ids and measurement + seqsBis.append(combined_seq + [Id(meas_qubit), Id(meas_qubit), MEAS(meas_qubit)]) + + # Append sequence with tomography pulses and measurement + seqsBis.append(combined_seq + [X90(meas_qubit), X90(meas_qubit), MEAS(meas_qubit)]) + + # Add the calibration sequences + seqsBis.append([Id(meas_qubit), Id(meas_qubit), Id(meas_qubit), Id(meas_qubit), MEAS(meas_qubit)]) + seqsBis.append([X90(meas_qubit), X90(meas_qubit), Id(meas_qubit), Id(meas_qubit), MEAS(meas_qubit)]) + seqsBis.append([X90(meas_qubit), X90(meas_qubit), X90(meas_qubit, **pi2args), X90(meas_qubit, **pi2args), MEAS(meas_qubit)]) + + axis_descriptor = [ + { + 'name': 'length', + 'unit': None, + 'points': [len(s) for s in seqs for i in range(2)], + 'partition': 1 + }, + { + 'name': 'calibration', + 'unit': 'state', + 'partition': 2, + 'points': ['0', '1', '2'] + }] + + metafile = compile_to_hardware(seqsBis, 'RB/LRB', axis_descriptor = axis_descriptor, extra_meta = {'sequences':seqs}) + + if showPlot: + plot_pulse_files(metafile) + return metafile + def SingleQubitRB_AC(qubit, seqs, purity=False, showPlot=False, add_cals=True): """Single qubit randomized benchmarking using atomic Clifford pulses. From d60d1099e053df2656b6fb1d54d9ef80a1cf09d7 Mon Sep 17 00:00:00 2001 From: Billy Date: Tue, 17 Dec 2019 11:41:16 -0500 Subject: [PATCH 20/25] Flat-top with 0 rise/fall --- QGL/PulsePrimitives.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/QGL/PulsePrimitives.py b/QGL/PulsePrimitives.py index a99a6e6a..ba908919 100644 --- a/QGL/PulsePrimitives.py +++ b/QGL/PulsePrimitives.py @@ -638,9 +638,12 @@ def flat_top_gaussian(chan, """ A constant pulse with rising and falling gaussian shape """ - p = Utheta(chan, length=riseFall, amp=amp, phase=phase, shape_fun=PulseShapes.gaussOn, label=label+"_rise") + \ - Utheta(chan, length=length, amp=amp, phase=phase, shape_fun=PulseShapes.constant, label=label+"_top") + \ - Utheta(chan, length=riseFall, amp=amp, phase=phase, shape_fun=PulseShapes.gaussOff, label=label+"_fall") + if riseFall == 0: + p = Utheta(chan, length=length, amp=amp, phase=phase, shape_fun=PulseShapes.constant, label=label+"_top") + else: + p = Utheta(chan, length=riseFall, amp=amp, phase=phase, shape_fun=PulseShapes.gaussOn, label=label+"_rise") + \ + Utheta(chan, length=length, amp=amp, phase=phase, shape_fun=PulseShapes.constant, label=label+"_top") + \ + Utheta(chan, length=riseFall, amp=amp, phase=phase, shape_fun=PulseShapes.gaussOff, label=label+"_fall") return p._replace(label=label) From a8dbba5def4d734c6e08f79da6e65830fa6b6e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Wed, 18 Dec 2019 12:16:12 -0500 Subject: [PATCH 21/25] Don't compare unique channels Among databases. i.e., don't try to compare properties of channels that only exist in one of the two databases --- QGL/ChannelLibraries.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index bd35deb7..1a06a43f 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -311,10 +311,13 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): return table_code table_code = '' - for chan, value in dict_1.items(): - this_dict = value.__dict__ + for chan in set(list(dict_1.keys()) + list(dict_2.keys())): + if chan not in dict_1 or chan not in dict_2: # don't display differences of unique channels + continue + this_dict1 = dict_1[chan].__dict__ + this_dict2 = dict_2[chan].__dict__ ct = 0 - table_code += iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) + table_code += iter_diff(this_dict1, this_dict2, ct, chan) display(HTML(f"{table_code}
ObjectParameter{name1}{name2}
")) def receivers(self): From 2a4dbab36f9a580b97cd24b8ef4989deb6e1b323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Thu, 9 Jan 2020 18:21:27 -0500 Subject: [PATCH 22/25] Show connectivity graph for device And relevant parameters, WIP --- QGL/ChannelLibraries.py | 73 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index bd35deb7..237c8fa2 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -55,7 +55,8 @@ from . import Channels from . import PulseShapes -from IPython.display import HTML, display +from ipywidgets import Layout, HTML +from IPython.display import HTML as IPHTML, display channelLib = None @@ -145,7 +146,7 @@ def ls(self): 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}{notes}" - display(HTML(f"{table_code}
idYearDateTimeNameNotes
")) + display(IPHTML(f"{table_code}
idYearDateTimeNameNotes
")) 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() @@ -233,6 +234,62 @@ def next_level(nodes, iteration=0, offset=0, accum=[]): fig = Figure(marks=[bq_graph], layout=fig_layout) return fig + def show_connectivity(self): + graph_edges = [] + qub_objs = self.qubits() + edges = self.edges() + for e in edges: + graph_edges.append((e.source.label, e.target.label)) + + table = HTML("Re-evaluate this plot to see information about qubits. Otherwise it will be stale.") + table.add_class("hover_tooltip") + display(IPHTML(""" + + """)) + + graph = nx.digraph.DiGraph() + for q in qub_objs: + graph.add_node(q.label, node_obj = q) + + graph.add_edges_from(graph_edges) + + indices = {n: i for i, n in enumerate(graph.nodes())} + node_data = [{'label': n, 'data': v['node_obj'].print(False)} for n,v in graph.nodes(True)] # fix node visualization + 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 = {} + + nqubits = len(qub_objs) + dtheta = 2*np.pi/nqubits + rho = 4 + x = [rho*np.cos(dtheta*ind) for ind,n in enumerate(qub_objs)] + y = [rho*np.sin(dtheta*ind) for ind,n in enumerate(qub_objs)] + hovered_symbol = '' + def hover_handler(self, content, hovered_symbol=hovered_symbol, table=table): + symbol = content.get('data', '') + if(symbol != hovered_symbol): + hovered_symbol = symbol + table.value = symbol['data'] + + 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='500px', 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=['blue'] * len(node_data), directed=True) + bgs_lines = [] + middles = [] + bq_graph.tooltip = table + bq_graph.on_hover(hover_handler) + fig = Figure(marks=[bq_graph], layout=fig_layout) + return fig + def show_frequency_plan(self): c_freqs = {} m_freqs = {} @@ -315,7 +372,7 @@ def iter_diff(value_iter1, value_iter2, ct, label=''): this_dict = value.__dict__ ct = 0 table_code += iter_diff(this_dict, dict_2[chan].__dict__, ct, chan) - display(HTML(f"{table_code}
ObjectParameter{name1}{name2}
")) + display(IPHTML(f"{table_code}
ObjectParameter{name1}{name2}
")) def receivers(self): return self.ent_by_type(Channels.Receiver) @@ -529,7 +586,7 @@ def new_APS2_rack(self, label, ip_addresses, tdm_ip=None, **kwargs): def new_transceiver(self, model, label, address, numtx=1, numrx=1, nummark=4, record_length = 1024, **kwargs): translator = model+"Pattern" stream_sel = model+"StreamSelector" - + chans = [] for i in range(numtx): chan = Channels.PhysicalQuadratureChannel(label=f"{label}-Tx{i+1}-1", instrument=label, channel=i, translator=translator, channel_db=self.channelDatabase) @@ -537,11 +594,11 @@ def new_transceiver(self, model, label, address, numtx=1, numrx=1, nummark=4, re for i in range(nummark): chan = Channels.PhysicalMarkerChannel(label=f"{label}-Tx{i+1}-M", channel=i, instrument=label, translator=translator, channel_db=self.channelDatabase) chans.append(chan) - + transmitter = Channels.Transmitter(label=f"{label}-Tx", model=model, address=address, channels=chans, channel_db=self.channelDatabase) transmitter.trigger_source = "external" transmitter.address = address - + chans = [] for i in range(numrx): chan = Channels.ReceiverChannel(label=f"RecvChan-{label}-{i+1}", channel=i, channel_db=self.channelDatabase) @@ -556,8 +613,8 @@ def new_transceiver(self, model, label, address, numtx=1, numrx=1, nummark=4, re transceiver = Channels.Transceiver(label=label, address=address, model=model, transmitters=[transmitter], receivers = [receiver], initialize_separately=False, channel_db=self.channelDatabase) transmitter.transceiver = transceiver receiver.transceiver = transceiver - - self.add_and_update_dict(transceiver) + + self.add_and_update_dict(transceiver) return transceiver From b5735dfa2c04abf902c6dc9328cb77a58684c7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Fri, 10 Jan 2020 14:47:34 -0500 Subject: [PATCH 23/25] Display CNOT properties --- QGL/ChannelLibraries.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/QGL/ChannelLibraries.py b/QGL/ChannelLibraries.py index 237c8fa2..d8b80e5f 100644 --- a/QGL/ChannelLibraries.py +++ b/QGL/ChannelLibraries.py @@ -47,7 +47,7 @@ import bbndb -from bqplot import Figure, LinearScale, Axis, Lines, Figure +from bqplot import Figure, LinearScale, ColorScale, Axis, Lines, Figure from bqplot.marks import Graph, Lines, Label from ipywidgets import Layout, VBox, HBox @@ -141,10 +141,10 @@ def ls(self): cdb = Channels.ChannelDatabase q = self.session.query(cdb.label, cdb.time, cdb.id, cdb.notes).\ order_by(-Channels.ChannelDatabase.id, Channels.ChannelDatabase.label, Channels.ChannelDatabase.notes).all() + table_code = "" for i, (label, time, id, notes) 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}{notes}" display(IPHTML(f"{table_code}
idYearDateTimeNameNotes
")) @@ -234,7 +234,7 @@ def next_level(nodes, iteration=0, offset=0, accum=[]): fig = Figure(marks=[bq_graph], layout=fig_layout) return fig - def show_connectivity(self): + def show_connectivity(self, verbose=False): graph_edges = [] qub_objs = self.qubits() edges = self.edges() @@ -258,7 +258,9 @@ def show_connectivity(self): graph.add_edges_from(graph_edges) indices = {n: i for i, n in enumerate(graph.nodes())} - node_data = [{'label': n, 'data': v['node_obj'].print(False)} for n,v in graph.nodes(True)] # fix node visualization + + node_data = [{'label': n, 'data': v['node_obj'].print(show=False, verbose=verbose), 'edge_data': v['node_obj'].print_edges(show=False, verbose=verbose, edges = [e for e in self.edges() if e.source.label == n or e.target.label == n] + )} for n,v in graph.nodes(True)] # fix edges link_data = [{'source': indices[s], 'target': indices[t]} for s, t in graph.edges()] qub_objs.sort(key=lambda x: x.label) @@ -278,15 +280,23 @@ def hover_handler(self, content, hovered_symbol=hovered_symbol, table=table): hovered_symbol = symbol table.value = symbol['data'] + def click_handler(self, content, hovered_symbol=hovered_symbol, table=table): + symbol = content.get('data', '') + if(symbol != hovered_symbol): + hovered_symbol = symbol + table.value = symbol['edge_data'] + 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='500px', 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=['blue'] * len(node_data), directed=True) + cs = ColorScale(scheme = 'PuBuGn') + bq_graph = Graph(node_data=node_data, link_data=link_data, x=x, y=y,scales={'x':xs, 'y':ys, 'color': cs}, + link_type='line', color=np.linspace(0,1,len(node_data)), directed=True) bgs_lines = [] middles = [] bq_graph.tooltip = table bq_graph.on_hover(hover_handler) + bq_graph.on_element_click(click_handler) fig = Figure(marks=[bq_graph], layout=fig_layout) return fig From b8c7620bbe2d8719b65c13e99ba3660a7adb0bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= Date: Thu, 16 Jan 2020 14:00:30 -0500 Subject: [PATCH 24/25] Update example.sqlite --- doc/example.sqlite | Bin 172032 -> 172032 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/example.sqlite b/doc/example.sqlite index 7facb43ed58303bf987b6d38fd113150a6c60d6d..832d3c99c8ecef71ebed6cd8a931777fc982363a 100644 GIT binary patch delta 3077 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 delta 2821 zcmd^9YitzP6~5=r%+6zH=I(mEo?Y**cf7mAn8e^+8>@C&D2<}fQvV2PLQ7F$vDXib z4PF}%N>kW1&hj}?nz2$pClN~D6?w2BIKNCk~jj031BkkItb z*b8ne^rA3r@-ewZt}B(& zvz|W)H~0hGP22~o;Y-7XUsE3zxMEnd#2ik5ZY|2;Tig&bD|LrLt(kQ^gy*n07Y5Yt}ebeHG#-`>b z`_s5!9_CH=v-wk^ulX!FOr9ZYNSa9cd-{a_1AVK$N`FB2X;-vK&DQp7?bP#x+>U51kk4~k8#=3N>f<;VELtSrUD(ILzGaKlNiwP%|Nd-#3(=}yIPN1PKt@;II z_~rg>8@mVlGf5wP?@uWp^sx)Ipws>fLD1;Y3kfchRGChJ*IgpxRA4X3iZQbxB|9d4 z{m%k>*tuZ3Ms&B8VcYV!!L*Ykl+1<{?0hS)#xhB+f;hg{r}m)BZbAR8~(rB_m^W4*0&P8jkHN+O8TB>xA0Z|2+y%V9&H*fJnqam zj}Ww3zwLn-gvY0Q*w8}IO83G-2w7`;;k)Bay?6&ex%G=a90J2S(}(v*1MW~48{A3C zZqMbjow+$xVby2h`%q@Rk!3s(9RF(;cu4H=`$Z!jhi~`0DO>Yf+HwN}Tk`jea=ZW7 z4N&&1^od3?3Ex>m<2V8V`Y@iNhsQ#8CAS3P>xoMa2mJ0L`CMDBo7FDqGP{eP0=nMw z7jDmIb=sp;0kQWhF|26p8i2fr$ct>Wo+W_}2%wH;IRJqOOD-dP4adS~Xm#F&Ru^dq&D-yvzs&VGp<`cDTU# z9gY0xF>8~?0^U?ux@w2!GDE*QBZ1&bus$8 zlTA=fM~(++{Pjy*aeI`~(S=~z6Qixb6`~O<+QptcZY}M?dqb6?VHhy7- zE2^y6Cb$v}&o;yyYj+Q9-JIRoKC5C@ya$eQduu{e9a{uZr=b1iu`bLRhG>0r15`t$ zb!Y<&%IuNO81drTB;9@@1vU1MPAr8=H^?d%wz!pN$;n};l(oGJ>a69PaEvc*s1WD% z@CqP9eO02dd^zmvantC?RG3=F!;r8?j&A~MUpFkF%SI|1HSJ|op-v-mk^G8SWRN_r zKSgByvOcN*L_erMP3rWFu4^A?Z>ZDSx3sldlUBwWb*L0E*vLnN; z3^AEtbA?j0FkMa8PM1;hS{Vc>xt63a&v^mnC2&%tA6`u*H7`QE`{FWsY~Mjd)PD;k zy!59mS(#x4WyfUf%A{E4jU;(Vrq`#VxY|P}W)k%HOf8+9i7_T+9$-2(ld!?$Oq+im zd;x{gW|_WDdtVz=_j%8G*D0&naat6vC|21|-t_>>7``*WhYAf*+WP4zZxnj`bp1a* z;L7qo8o$%e@phQySp$2*t|5Cuu9n1#5+Yba zl+Pgoa|mwCDO<<6O z_&=bds8U;yOqXB&%akv1ST5jDS96@M8CeX;@mqbMgTj#+MDCEklNolemx!N_aR{QE Lk8@gpnfgBgX4VKh From 06f6ab38c026f562e7c53d3ad29ce56c5ade8989 Mon Sep 17 00:00:00 2001 From: Graham Rowlands Date: Tue, 21 Jan 2020 15:04:00 -0500 Subject: [PATCH 25/25] Version and requirements bumps --- requirements.txt | 4 ++-- setup.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index 5091a385..d0054aad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -bbndb >= 2019.2 +bbndb >= 2020.1 numpy >= 1.11.1 scipy >= 0.17.1 networkx >= 1.11 -bqplot >= 0.11.5 +bqplot >= 0.12.2 sqlalchemy >= 1.2.15 \ No newline at end of file diff --git a/setup.py b/setup.py index 8aa67efe..520799fa 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,17 @@ from setuptools import setup, find_packages setup(name='QGL', - version='2019.2', + version='2020.1', packages=find_packages(exclude=["tests"]), url='https://github.com/BBN-Q/QGL', download_url='https://github.com/BBN-Q/QGL', license="Apache 2.0 License", install_requires=[ - "bbndb >= 2019.2", + "bbndb >= 2020.1", "numpy >= 1.11.1", "scipy >= 0.17.1", "networkx >= 1.11", - "bqplot >= 0.11.5", + "bqplot >= 0.12.2", "sqlalchemy >= 1.2.15" ], description="Quantum Gate Language (QGL) is a domain specific language embedded in python for specifying pulse sequences.",