Beispiel #1
0
def compile_to_hardware(seqs, fileName=None, suffix='', alignMode="right", nbrRepeats=1):
    #Add the digitizer trigger to each sequence
    #TODO: Make this more sophisticated.
    PatternUtils.add_digitizer_trigger(seqs, channelLib['digitizerTrig'])
    
    # normalize sequences
    channels = set([])
    for seq in seqs:
        channels |= find_unique_channels(seq)
    seqs = [normalize(seq, channels) for seq in seqs]

    #Compile all the pulses/pulseblocks to linklists and waveform libraries
    linkLists, wfLib = compile_sequences(seqs)

    # align channels
    # this horrible line finds the longest miniLL across all channels
    longestLL = max([sum([entry.totLength for entry in miniLL]) for LL in linkLists.values() for miniLL in LL])
    
    for chan, LL in linkLists.items():
        PatternUtils.align(LL, alignMode, longestLL+SEQUENCE_PADDING)

    #Add the slave trigger
    #TODO: only add to slave devices
    linkLists[channelLib['slaveTrig']], wfLib[channelLib['slaveTrig']] = PatternUtils.slave_trigger(len(seqs))

    # map logical to physical channels
    awgData = map_logical_to_physical(linkLists, wfLib)

    # for each physical channel need to:
    # 1) delay
    # 2) apply SSB if necessary
    # 3) mixer correct
    for awgName, awg in awgData.items():
        for chanName, chanData in awg.items():
            if chanData:
                # construct IQkey using existing convention
                IQkey = awgName + '-' + chanName[2:]
                chanObj = channelLib[IQkey]
                #We handle marker and quadrature channels differently
                #For now that is all we handle
                if isinstance(chanObj, Channels.PhysicalQuadratureChannel):
                    #Apply mixer corrections and channel delay 
                    PatternUtils.delay(chanData['linkList'], chanObj.delay + chanObj.AWG.delay, chanObj.samplingRate)

                    #At this point we finally have the timing of all the pulses so we can apply SSB
                    if hasattr(chanObj, 'SSBFreq') and abs(chanObj.SSBFreq) > 0:
                        PatternUtils.apply_SSB(chanData['linkList'], chanData['wfLib'], chanObj.SSBFreq, chanObj.samplingRate)

                    PatternUtils.correctMixer(chanData['wfLib'], chanObj.correctionT)

                    # add gate pulses on the marker channel
                    # note that the marker may be on an entirely different AWG
                    markerAwgName, markerKey = chanObj.gateChan.label.split('-')
                    markerKey = 'ch' + markerKey
                    markerAwg = awgData[markerAwgName]
                    genObj = chanObj.generator
                    #TODO: check if this actually catches overwriting markers
                    if markerAwg[markerKey]:
                        warn('Reuse of marker gating channel: {0}'.format(markerKey))
                    markerAwg[markerKey] = {'linkList':None, 'wfLib':markerWFLib}
                    markerAwg[markerKey]['linkList'] = PatternUtils.create_gate_seqs(
                        chanData['linkList'], genObj.gateBuffer, genObj.gateMinWidth, chanObj.samplingRate)
                    markerDelay = genObj.gateDelay + chanObj.gateChan.delay + (chanObj.AWG.delay - chanObj.gateChan.AWG.delay)
                    PatternUtils.delay(markerAwg[markerKey]['linkList'], markerDelay, chanObj.gateChan.samplingRate )


                elif isinstance(chanObj, Channels.PhysicalMarkerChannel):
                    PatternUtils.delay(chanData['linkList'], chanObj.delay+chanObj.AWG.delay, chanObj.samplingRate)

                else:
                    raise NameError('Unable to handle channel type.')

                #Remove unused waveforms
                compress_wfLib(chanData['linkList'], chanData['wfLib'])

    #Loop back through to fill empty channels and write to file
    fileList = []
    for awgName, awg in awgData.items():
        #If all the channels are empty then do not bother writing the file
        if not all([chan is None for chan in awg.values()]):
            for chan in awg.keys():
                if not awg[chan]:
                    #"Seems hackish but check for marker
                    if chan[-2] == 'm':
                        awg[chan] = {'linkList': [[create_padding_LL(SEQUENCE_PADDING//2), create_padding_LL(SEQUENCE_PADDING//2)]],
                                 'wfLib': markerWFLib}
                    else:
                        awg[chan] = {'linkList': [[create_padding_LL(SEQUENCE_PADDING//2), create_padding_LL(SEQUENCE_PADDING//2)]],
                                 'wfLib': {TAZKey:np.zeros(1, dtype=np.complex)}}

            # convert to hardware formats
            # create the target folder if it does not exist
            targetFolder = os.path.split(os.path.normpath(os.path.join(config.AWGDir, fileName)))[0]
            if not os.path.exists(targetFolder):
                os.mkdir(targetFolder)
            fullFileName = os.path.normpath(os.path.join(config.AWGDir, fileName + '-' + awgName + suffix + instrumentLib[awgName].seqFileExt))
            if isinstance(instrumentLib[awgName], APS):
                write_APS_file(awg, fullFileName, nbrRepeats)
            elif isinstance(instrumentLib[awgName], Tek5014):
                assert nbrRepeats == 1, 'nbrRepeats > 1 not implemented for the Tek'
                write_Tek_file(awg, fullFileName, fileName)
            else:
                raise NameError('Unknown AWG type')
            fileList.append(fullFileName)

    #Return the filenames we wrote
    return fileList
Beispiel #2
0
def compile_to_hardware(seqs,
                        fileName=None,
                        suffix='',
                        alignMode="right",
                        nbrRepeats=1):
    #Add the digitizer trigger to each sequence
    #TODO: Make this more sophisticated.
    PatternUtils.add_digitizer_trigger(seqs, channelLib['digitizerTrig'])

    # normalize sequences
    channels = set([])
    for seq in seqs:
        channels |= find_unique_channels(seq)
    seqs = [normalize(seq, channels) for seq in seqs]

    #Compile all the pulses/pulseblocks to linklists and waveform libraries
    linkLists, wfLib = compile_sequences(seqs)

    # align channels
    # this horrible line finds the longest miniLL across all channels
    longestLL = max([
        sum([entry.totLength for entry in miniLL])
        for LL in linkLists.values() for miniLL in LL
    ])

    for chan, LL in linkLists.items():
        PatternUtils.align(LL, alignMode, longestLL + SEQUENCE_PADDING)

    #Add the slave trigger
    #TODO: only add to slave devices
    linkLists[channelLib['slaveTrig']], wfLib[
        channelLib['slaveTrig']] = PatternUtils.slave_trigger(len(seqs))

    # map logical to physical channels
    awgData = map_logical_to_physical(linkLists, wfLib)

    # for each physical channel need to:
    # 1) delay
    # 2) apply SSB if necessary
    # 3) mixer correct
    for awgName, awg in awgData.items():
        for chanName, chanData in awg.items():
            if chanData:
                # construct IQkey using existing convention
                IQkey = awgName + '-' + chanName[2:]
                chanObj = channelLib[IQkey]
                #We handle marker and quadrature channels differently
                #For now that is all we handle
                if isinstance(chanObj, Channels.PhysicalQuadratureChannel):
                    #Apply mixer corrections and channel delay
                    PatternUtils.delay(chanData['linkList'],
                                       chanObj.delay + chanObj.AWG.delay,
                                       chanObj.samplingRate)

                    #At this point we finally have the timing of all the pulses so we can apply SSB
                    if hasattr(chanObj,
                               'SSBFreq') and abs(chanObj.SSBFreq) > 0:
                        PatternUtils.apply_SSB(chanData['linkList'],
                                               chanData['wfLib'],
                                               chanObj.SSBFreq,
                                               chanObj.samplingRate)

                    PatternUtils.correctMixer(chanData['wfLib'],
                                              chanObj.correctionT)

                    # add gate pulses on the marker channel
                    # note that the marker may be on an entirely different AWG
                    markerAwgName, markerKey = chanObj.gateChan.name.split('-')
                    markerKey = 'ch' + markerKey
                    markerAwg = awgData[markerAwgName]
                    genObj = chanObj.generator
                    #TODO: check if this actually catches overwriting markers
                    if markerAwg[markerKey]:
                        warn('Reuse of marker gating channel: {0}'.format(
                            markerKey))
                    markerAwg[markerKey] = {
                        'linkList': None,
                        'wfLib': markerWFLib
                    }
                    markerAwg[markerKey][
                        'linkList'] = PatternUtils.create_gate_seqs(
                            chanData['linkList'], genObj.gateBuffer,
                            genObj.gateMinWidth, chanObj.samplingRate)
                    markerDelay = genObj.gateDelay + chanObj.gateChan.delay + (
                        chanObj.AWG.delay - chanObj.gateChan.AWG.delay)
                    PatternUtils.delay(markerAwg[markerKey]['linkList'],
                                       markerDelay,
                                       chanObj.gateChan.samplingRate)

                elif isinstance(chanObj, Channels.PhysicalMarkerChannel):
                    PatternUtils.delay(chanData['linkList'],
                                       chanObj.delay + chanObj.AWG.delay,
                                       chanObj.samplingRate)

                else:
                    raise NameError('Unable to handle channel type.')

    #Loop back through to fill empty channels and write to file
    fileList = []
    for awgName, awg in awgData.items():
        #If all the channels are empty then do not bother writing the file
        if not all([chan is None for chan in awg.values()]):
            for chan in awg.keys():
                if not awg[chan]:
                    #"Seems hackish but check for marker
                    if chan[-2] == 'm':
                        awg[chan] = {
                            'linkList': [[
                                create_padding_LL(SEQUENCE_PADDING // 2),
                                create_padding_LL(SEQUENCE_PADDING // 2)
                            ]],
                            'wfLib':
                            markerWFLib
                        }
                    else:
                        awg[chan] = {
                            'linkList': [[
                                create_padding_LL(SEQUENCE_PADDING // 2),
                                create_padding_LL(SEQUENCE_PADDING // 2)
                            ]],
                            'wfLib': {
                                TAZKey: np.zeros(1, dtype=np.complex)
                            }
                        }

            # convert to hardware formats
            # create the target folder if it does not exist
            targetFolder = os.path.split(config.AWGDir + fileName)[0]
            if not os.path.exists(targetFolder):
                os.mkdir(targetFolder)
            fullFileName = config.AWGDir + fileName + '-' + awgName + suffix + instrumentLib[
                awgName].seqFileExt
            if isinstance(instrumentLib[awgName], APS):
                write_APS_file(awg, fullFileName, nbrRepeats)
            elif isinstance(instrumentLib[awgName], Tek5014):
                assert nbrRepeats == 1, 'nbrRepeats > 1 not implemented for the Tek'
                write_Tek_file(awg, fullFileName, fileName)
            else:
                raise NameError('Unknown AWG type')
            fileList.append(fullFileName)

    #Return the filenames we wrote
    return fileList