def create_meas_pulse(qubit): if isinstance(qubit, Channels.Qubit): #Deal with single qubit readout channel channelName = "M-" + qubit.label elif isinstance(qubit, tuple): #Deal with joint readout channel and MUX measChanList = [] paramsList = [] lenList = [] channelName = "M-" for q in qubit: channelName += q.label measChanList += [Channels.MeasFactory("M-" + q.label)] paramsList += [overrideDefaults(measChanList[-1], kwargs)] lenList += [ len(measChanList[-1].pulseParams['shapeFun']( **paramsList[-1])) ] measChan = Channels.MeasFactory(channelName) # measurement channels should have just an "amp" parameter timeStep = 1.0 / measChan.physChan.samplingRate measShapeSum = np.zeros(max(lenList), dtype=complex) for i, q in enumerate(qubit): measShape = measChanList[i].pulseParams['shapeFun']( **paramsList[i]) timePts = np.linspace(0, paramsList[i]['length'], lenList[i]) measShape *= np.exp(-1j * 2 * pi * measChanList[i].autodyneFreq * timePts) measShapeSum += np.array(measShape.tolist() + [0] * (max(lenList) - lenList[i])) return Pulse("MEAS", measChan, measShapeSum, 0.0, 0.0)
def CNOT(source, target): # construct (source, target) channel and pull parameters from there twoQChannel = Channels.QubitFactory(source.name + target.name) shape = twoQChannel.pulseParams['shapeFun']( amp=twoQChannel.pulseParams['piAmp'], **overrideDefaults(twoQChannel, {})) return Pulse("CNOT", (source, target), shape, 0.0, 0.0)
def arb_axis_drag(qubit, nutFreq, rotAngle=0, polarAngle=0, aziAngle=0, **kwargs): """ Single qubit arbitrary axis pulse implemented with phase ramping and frame change. For now we assume gaussian shape. Parameters ---------- qubit : logical channel nutFreq: effective nutation frequency per unit of drive amplitude (Hz) rotAngle : effective rotation rotAngle (radians) polarAngle : polar angle of rotation axis (radians) aziAngle : azimuthal (radians) """ params = overrideDefaults(qubit, kwargs) # TODO: figure out way to reduce code duplication between this and the pulse shape if params['length'] > 0: #To calculate the phase ramping we'll need the sampling rate sampRate = qubit.physChan.samplingRate #Start from a gaussian shaped pulse gaussPulse = PulseShapes.gaussian(amp=1, samplingRate=sampRate, **params).real #Scale to achieve to the desired rotation calScale = (rotAngle / 2 / pi) * sampRate / sum(gaussPulse) #Calculate the phase ramp steps to achieve the desired Z component to the rotation axis phaseSteps = -2 * pi * cos( polarAngle) * calScale * gaussPulse / sampRate #Calculate Z DRAG correction to phase steps #beta is a conversion between XY drag scaling and Z drag scaling beta = params['dragScaling'] / sampRate instantaneousDetuning = beta * (2 * pi * calScale * sin(polarAngle) * gaussPulse)**2 phaseSteps = phaseSteps + instantaneousDetuning * (1.0 / sampRate) frameChange = sum(phaseSteps) elif abs(polarAngle) < 1e-10: #Otherwise assume we have a zero-length Z rotation frameChange = -rotAngle else: raise ValueError( 'Non-zero transverse rotation with zero-length pulse.') params['nutFreq'] = nutFreq params['rotAngle'] = rotAngle params['polarAngle'] = polarAngle params['shapeFun'] = PulseShapes.arb_axis_drag return Pulse("ArbAxis", qubit, params, 1.0, aziAngle, frameChange)
def arb_axis_drag(qubit, nutFreq, rotAngle=0, polarAngle=0, aziAngle=0, **kwargs): """ Single qubit arbitrary axis pulse implemented with phase ramping and frame change. For now we assume gaussian shape. Parameters ---------- qubit : logical channel nutFreq: effective nutation frequency per unit of drive amplitude (Hz) rotAngle : effective rotation rotAngle (radians) polarAngle : polar angle of rotation axis (radians) aziAngle : azimuthal (radians) """ params = overrideDefaults(qubit, kwargs) if params['length'] > 0: #Start from a gaussian shaped pulse gaussPulse = PulseShapes.gaussian(amp=1, **params) #To calculate the phase ramping we'll need the sampling rate sampRate = qubit.physChan.samplingRate #Scale to achieve to the desired rotation calScale = (rotAngle / 2 / pi) * sampRate / sum(gaussPulse) #Calculate the phase ramp steps to achieve the desired Z component to the rotation axis phaseSteps = -2 * pi * cos( polarAngle) * calScale * gaussPulse / sampRate #Calculate Z DRAG correction to phase steps #beta is a conversion between XY drag scaling and Z drag scaling beta = params['dragScaling'] / sampRate instantaneousDetuning = beta * (2 * pi * calScale * sin(polarAngle) * gaussPulse)**2 phaseSteps = phaseSteps + instantaneousDetuning * (1.0 / sampRate) #center phase ramp around the middle of the pulse time steps phaseRamp = np.cumsum(phaseSteps) - phaseSteps / 2 frameChange = sum(phaseSteps) shape = (1.0 / nutFreq) * sin(polarAngle) * calScale * np.exp( 1j * aziAngle) * gaussPulse * np.exp(1j * phaseRamp) elif abs(polarAngle) < 1e-10: #Otherwise assume we have a zero-length Z rotation frameChange = -rotAngle shape = np.array([], dtype=np.complex128) else: raise ValueError( 'Non-zero transverse rotation with zero-length pulse.') return Pulse("ArbAxis", qubit, shape, 0.0, frameChange)
def add_digitizer_trigger(seqs, trigChan): ''' Add the digitizer trigger. For now hardcoded but should be loaded from config file. ''' #Assume that last pulse is the measurment pulse for now and tensor on the digitizer trigger pulse for seq in seqs: #Hack around copied list elements referring to same sequence element if isinstance(seq[-1], Pulse) or trigChan not in seq[-1].pulses.keys(): seq[-1] *= Pulse( "digTrig", trigChan, trigChan.pulseParams['shapeFun'](**trigChan.pulseParams), 0.0, 0.0)
def create_meas_pulse(qubit): if isinstance(qubit, Channels.Qubit): #Deal with single qubit readout channel channelName = "M-" + qubit.label elif isinstance(qubit, tuple): #Deal with joint readout channel channelName = "M-" for q in qubit: channelName += q.label measChan = Channels.MeasFactory(channelName) params = overrideDefaults(measChan, kwargs) params['frequency'] = measChan.autodyneFreq params['baseShape'] = params.pop('shapeFun') params['shapeFun'] = PulseShapes.autodyne amp = params.pop('amp') return Pulse("MEAS", measChan, params, amp, 0.0, 0.0)
def create_meas_pulse(qubit): if isinstance(qubit, Channels.Qubit): #Deal with single qubit readout channel channelName = "M-" + qubit.name elif isinstance(qubit, tuple): #Deal with joint readout channel channelName = "M-" for q in qubit: channelName += q.name measChan = Channels.MeasFactory(channelName) params = overrideDefaults(measChan, kwargs) # measurement channels should have just an "amp" parameter measShape = measChan.pulseParams['shapeFun'](**params) #Apply the autodyne frequency timeStep = 1.0 / measChan.physChan.samplingRate timePts = np.linspace(0, params['length'], len(measShape)) measShape *= np.exp(-1j * 2 * pi * measChan.autodyneFreq * timePts) return Pulse("MEAS", measChan, measShape, 0.0, 0.0)
def U(qubit, phase=0, **kwargs): ''' A generic 180 degree rotation with variable phase. ''' params = overrideDefaults(qubit, kwargs) shape = params['shapeFun'](amp=qubit.pulseParams['piAmp'], **params) return Pulse("U", qubit, shape, phase, 0.0)
def Ytheta(qubit, amp=0, **kwargs): ''' A generic Y rotation with a variable amplitude ''' params = overrideDefaults(qubit, kwargs) shape = params['shapeFun'](amp=amp, **params) return Pulse("Ytheta", qubit, shape, pi / 2, 0.0)
def Ztheta(qubit, angle=0, **kwargs): return Pulse("Ztheta", qubit, np.array([], dtype=np.complex128), 0, -angle)
def Z90m(qubit, **kwargs): return Pulse("Z90m", qubit, np.array([], dtype=np.complex128), 0, pi / 2)
def Y90m(qubit, **kwargs): shape = qubit.pulseParams['shapeFun'](amp=qubit.pulseParams['pi2Amp'], **overrideDefaults(qubit, kwargs)) return Pulse("Y90m", qubit, shape, -pi / 2, 0.0)
def Xm(qubit, **kwargs): shape = qubit.pulseParams['shapeFun'](amp=qubit.pulseParams['piAmp'], **overrideDefaults(qubit, kwargs)) return Pulse("Xm", qubit, shape, pi, 0.0)
def Utheta(qubit, amp=0, phase=0, **kwargs): ''' A generic rotation with variable amplitude and phase. ''' params = overrideDefaults(qubit, kwargs) shape = params['shapeFun'](amp=amp, **params) return Pulse("Utheta", qubit, shape, phase, 0.0)
def Utheta(qubit, amp=0, phase=0, label='Utheta', **kwargs): ''' A generic rotation with variable amplitude and phase. ''' params = overrideDefaults(qubit, kwargs) return Pulse(label, qubit, params, amp, phase, 0.0)
def CNOT(source, target, **kwargs): # construct (source, target) channel and pull parameters from there channel = Channels.QubitFactory(source.label + target.label) params = overrideDefaults(channel, kwargs) return Pulse("CNOT", (source, target), params, channel.pulseParams['piAmp'], 0.0, 0.0)