def set_tone_bins(self, bins, nsamp, amps=None, load=True, normfact=None, phases=None, preset_norm=True):
        """
        Set the stimulus tones by specific integer bins

        bins : array of bins at which tones should be placed
            For Heterodyne system, negative frequencies should be placed in cannonical FFT order
            If 2d, interpret as (nwaves,ntones)
        nsamp : int, must be power of 2
            number of samples in the playback buffer. Frequency resolution will be fs/nsamp
        amps : optional array of floats, same length as bins array
            specify the relative amplitude of each tone. Can set to zero to read out a portion
            of the spectrum with no stimulus tone.
        load : bool (debug only). If false, don't actually load the waveform, just calculate it.
        """
        if self.BYTES_PER_SAMPLE * nsamp > self.MEMORY_SIZE_BYTES:
            message = "Requested tone size ({:d} bytes) exceeds available memory ({:d} bytes)"
            raise ValueError(message.format(self.BYTES_PER_SAMPLE * nsamp, self.MEMORY_SIZE_BYTES))
        if bins.ndim == 1:
            bins.shape = (1, bins.shape[0])
        nwaves = bins.shape[0]
        spec = np.zeros((nwaves, nsamp), dtype='complex')
        self.tone_bins = bins.copy()
        self.tone_nsamp = nsamp
        #this is to make sure phases are correct shape since we are reusing phases
        if phases is None or phases.shape[0] != bins.shape[1]:
            phases = np.random.random(bins.shape[1]) * 2 * np.pi
        self.phases = phases.copy()
        if amps is None:
            amps = 1.0
        self.amps = amps
        for k in range(nwaves):
            spec[k, bins[k, :]] = amps * np.exp(1j * phases)
        wave = np.fft.ifft(spec, axis=1)
        if preset_norm:
            self.wavenorm = calc_wavenorm(bins.shape[1], nsamp)
        else:
            self.wavenorm = np.abs(wave).max()
        if normfact is not None:
            wn = (2.0 / normfact) * len(bins) / float(nsamp)
            print "ratio of current wavenorm to optimal:", self.wavenorm / wn
            self.wavenorm = wn
        q_rwave = np.round((wave.real / self.wavenorm) * (2 ** 15 - 1024)).astype('>i2')
        q_iwave = np.round((wave.imag / self.wavenorm) * (2 ** 15 - 1024)).astype('>i2')
        q_iwave = np.roll(q_iwave, self.iq_delay, axis=1)
        q_rwave.shape = (q_rwave.shape[0] * q_rwave.shape[1],)
        q_iwave.shape = (q_iwave.shape[0] * q_iwave.shape[1],)
        self.q_rwave = q_rwave
        self.q_iwave = q_iwave
        if load:
            self.load_waveforms(q_rwave,q_iwave)
        self.save_state()
Exemple #2
0
    def add_tone_bins(self, bins, amps=None, preset_norm=True):
        nsamp = self.tone_nsamp
        spec = np.zeros((nsamp,), dtype='complex')
        self.tone_bins = np.vstack((self.tone_bins, bins))
        phases = self.phases
        if amps is None:
            amps = 1.0
        # self.amps = amps  # TODO: Need to figure out how to deal with this

        spec[bins] = amps * np.exp(1j * phases)
        wave = np.fft.ifft(spec)
        if preset_norm:
            self.wavenorm = calc_wavenorm(self.tone_bins.shape[1], nsamp)
        else:
            self.wavenorm = np.abs(wave).max()
        q_rwave = np.round((wave.real / self.wavenorm) * (2 ** 15 - 1024)).astype('>i2')
        q_iwave = np.round((wave.imag / self.wavenorm) * (2 ** 15 - 1024)).astype('>i2')
        q_iwave = np.roll(q_iwave, self.iq_delay, axis=0)
        start_offset = self.tone_bins.shape[0] - 1
        self.load_waveforms(q_rwave, q_iwave, start_offset=start_offset)
        self.save_state()
Exemple #3
0
    def add_tone_bins(self, bins, amps=None, preset_norm=True):
        nsamp = self.tone_nsamp
        spec = np.zeros((nsamp, ), dtype='complex')
        self.tone_bins = np.vstack((self.tone_bins, bins))
        phases = self.phases
        if amps is None:
            amps = 1.0
        # self.amps = amps  # TODO: Need to figure out how to deal with this

        spec[bins] = amps * np.exp(1j * phases)
        wave = np.fft.ifft(spec)
        if preset_norm:
            self.wavenorm = calc_wavenorm(self.tone_bins.shape[1], nsamp)
        else:
            self.wavenorm = np.abs(wave).max()
        q_rwave = np.round(
            (wave.real / self.wavenorm) * (2**15 - 1024)).astype('>i2')
        q_iwave = np.round(
            (wave.imag / self.wavenorm) * (2**15 - 1024)).astype('>i2')
        q_iwave = np.roll(q_iwave, self.iq_delay, axis=0)
        start_offset = self.tone_bins.shape[0] - 1
        self.load_waveforms(q_rwave, q_iwave, start_offset=start_offset)
        self.save_state()
Exemple #4
0
    def set_tone_bins(self,
                      bins,
                      nsamp,
                      amps=None,
                      load=True,
                      normfact=None,
                      phases=None,
                      preset_norm=True):
        """
        Set the stimulus tones by specific integer bins

        bins : array of bins at which tones should be placed
            For Heterodyne system, negative frequencies should be placed in cannonical FFT order
            If 2d, interpret as (nwaves,ntones)
        nsamp : int, must be power of 2
            number of samples in the playback buffer. Frequency resolution will be fs/nsamp
        amps : optional array of floats, same length as bins array
            specify the relative amplitude of each tone. Can set to zero to read out a portion
            of the spectrum with no stimulus tone.
        load : bool (debug only). If false, don't actually load the waveform, just calculate it.
        """
        if self.BYTES_PER_SAMPLE * nsamp > self.MEMORY_SIZE_BYTES:
            message = "Requested tone size ({:d} bytes) exceeds available memory ({:d} bytes)"
            raise ValueError(
                message.format(self.BYTES_PER_SAMPLE * nsamp,
                               self.MEMORY_SIZE_BYTES))
        if bins.ndim == 1:
            bins.shape = (1, bins.shape[0])
        nwaves = bins.shape[0]
        spec = np.zeros((nwaves, nsamp), dtype='complex')
        self.tone_bins = bins.copy()
        self.tone_nsamp = nsamp
        #this is to make sure phases are correct shape since we are reusing phases
        if phases is None or phases.shape[0] != bins.shape[1]:
            phases = np.random.random(bins.shape[1]) * 2 * np.pi
        self.phases = phases.copy()
        if amps is None:
            amps = 1.0
        self.amps = amps
        for k in range(nwaves):
            spec[k, bins[k, :]] = amps * np.exp(1j * phases)
        wave = np.fft.ifft(spec, axis=1)
        if preset_norm:
            self.wavenorm = calc_wavenorm(bins.shape[1], nsamp)
        else:
            self.wavenorm = np.abs(wave).max()
        if normfact is not None:
            wn = (2.0 / normfact) * len(bins) / float(nsamp)
            print "ratio of current wavenorm to optimal:", self.wavenorm / wn
            self.wavenorm = wn
        q_rwave = np.round(
            (wave.real / self.wavenorm) * (2**15 - 1024)).astype('>i2')
        q_iwave = np.round(
            (wave.imag / self.wavenorm) * (2**15 - 1024)).astype('>i2')
        q_iwave = np.roll(q_iwave, self.iq_delay, axis=1)
        q_rwave.shape = (q_rwave.shape[0] * q_rwave.shape[1], )
        q_iwave.shape = (q_iwave.shape[0] * q_iwave.shape[1], )
        self.q_rwave = q_rwave
        self.q_iwave = q_iwave
        if load:
            self.load_waveforms(q_rwave, q_iwave)
        self.save_state()