Exemple #1
0
    def _transfer_steps(self, steps):
        """ Writes all sequence steps passed, potentially overwriting.

        Parameters
        ----------
        steps : list of :class:`wavgen.utilities.Step`
            Sequence steps to write.
        """
        verboseprint('Beginning transfer of Steps to Board memory')
        for step in steps:
            cur = step.CurrentStep
            seg = step.SegmentIndex
            loop = step.Loops
            nxt = step.NextStep
            tran = step.Transition
            reg_upper = int32(tran | loop)
            reg_lower = int32(nxt << 16 | seg)
            debugprint("\tStep %.2d: 0x%08x_%08x\n" %
                       (cur, reg_upper.value, reg_lower.value))
            spcm_dwSetParam_i64m(self.hCard, SPC_SEQMODE_STEPMEM0 + cur,
                                 reg_upper, reg_lower)

        if DEBUG:
            print("\nDump!:\n")
            for i in range(len(steps)):
                temp = uint64(0)
                spcm_dwGetParam_i64(self.hCard, SPC_SEQMODE_STEPMEM0 + i,
                                    byref(temp))
                print("\tStep %.2d: 0x%08x_%08x\n" %
                      (i, int32(temp.value >> 32).value, int32(
                          temp.value).value))
                print("\t\tAlso: %16x\n" % temp.value)
Exemple #2
0
    def load_sequence(self, waveforms=None, steps=None):
        """ Transfers sequence waveforms and/or transition steps to board.

        Parameters
        ----------
        waveforms : list of :class:`~.waveform.Waveform`, list of (int, :class:`~wavgen.waveform.Waveform`)
            Waveform objects to each be written to a board segment.
            If each is paired with an index, then the corresponding segment indices are overwritten.
            You can only overwrite if an initial sequence is present on board.
        steps : list of :class:`~wavgen.utilities.Step`
            Transition steps which define looping & order of segment playback.

        See Also
        --------
        :class:`wavgen.utilities.Step`

        Examples
        --------
        Transferring an initial sequence::

            hCard  # Opened & configured Board handle
            myWaves = [wav0, wav2, wav3]
            mySteps = [step1, step3]  # A
            hCard.load_sequence(myWaves, mySteps)
            hCard.load_sequence(myWaves)
            hCard.load_sequence(steps=mySteps)


        """
        assert steps or waveforms, "No data given to load!"

        ## Card Configuration ##
        if not self.ChanReady:  # Sets channels to default mode if no user setting
            self.setup_channels()
        if not self.Sequence:  # Ensures the Card is set to Sequential Mode
            verboseprint("Setting Sequence mode")
            spcm_dwSetParam_i32(self.hCard, SPC_CARDMODE, SPC_REP_STD_SEQUENCE)

        ## Create default indices if none provided ##
        if isinstance(waveforms[0], tuple):
            indices = [i for i, _ in waveforms]
            waveforms = [wav for _, wav in waveforms]
        else:
            indices = np.arange(len(waveforms))

        ## Transfers provided Data ##
        if waveforms:
            self._transfer_sequence(waveforms, indices)
        if steps:
            self._transfer_steps(steps)  # Loads the sequence steps to card

        ## Wrap Up ##
        self._setup_clock()
        self._error_check()
        self.BufReady = True
        self.Sequence = True
Exemple #3
0
    def _transfer_sequence(self, wavs, indices):
        """ Tries to write each waveform, from a set, to an indicated board memory segment.

        Parameters
        ----------
        wavs : list of :class:`~wavgen.waveform.Waveform`
            Waveforms to write.
        indices : list of int, None
            The segment indices corresponding to the waveforms.
        """
        ## Checks the Board Memory's current division ##
        segs = int32(0)
        spcm_dwGetParam_i32(self.hCard, SPC_SEQMODE_MAXSEGMENTS, byref(segs))
        segs = max(segs.value, 1)

        ## Re-Divides the Board Memory if necessary ##
        if segs <= max(indices):
            verboseprint("Dividing Board Memory")
            while segs < max(indices):
                segs *= 2  # Halves all segments, doubling available segments

            spcm_dwSetParam_i32(self.hCard, SPC_SEQMODE_MAXSEGMENTS, segs)
            spcm_dwSetParam_i32(self.hCard, SPC_SEQMODE_STARTSTEP, 0)

        ## Checks that each wave can fit in the allowed segments ##
        limit = MEM_SIZE / (segs * 2)  # Segment capacity in samples
        max_wav = max([wav.SampleLength for wav in wavs])
        assert max_wav <= limit, "%i waves limits each segment to %i samples." % (
            len(wavs), limit)

        ## Sets up a local Software Buffer for Transfer to Board ##
        pv_buf = pvAllocMemPageAligned(NUMPY_MAX * 2)  # Allocates space on PC
        pn_buf = cast(pv_buf, ptr16)  # Casts pointer into something usable

        # Writes each waveform from the sequence to a corresponding segment on Board Memory ##
        verboseprint('Beginning Transfer of Waveform data to Board memory.')
        for itr, (idx, wav) in enumerate(zip(indices, wavs)):
            verboseprint(
                "\tTransferring Seg %d of size %d bytes to index %d..." %
                (itr, wav.SampleLength * 2, idx))
            start = time()
            spcm_dwSetParam_i32(self.hCard, SPC_SEQMODE_WRITESEGMENT,
                                int32(idx))
            spcm_dwSetParam_i32(self.hCard, SPC_SEQMODE_SEGMENTSIZE,
                                int32(wav.SampleLength))
            self._error_check()

            self._write_segment([wav], pv_buf, pn_buf)
            self._error_check()

            verboseprint("\t\tAverage Transfer rate: %d bytes/second" %
                         (wav.SampleLength * 2 // (time() - start)))
            verboseprint("Total Transfer %d%c" %
                         (int(100 * (itr + 1) / len(wavs)), '%'))
Exemple #4
0
 def _setup_clock(self):
     """ Tries to achieve requested sampling frequency (see global parameter :data:`~wavgen.config.SAMP_FREQ`)
     """
     spcm_dwSetParam_i32(
         self.hCard, SPC_CLOCKMODE,
         SPC_CM_INTPLL)  # Sets out internal Quarts Clock For Sampling
     spcm_dwSetParam_i64(self.hCard, SPC_SAMPLERATE,
                         int64(int(SAMP_FREQ)))  # Sets Sampling Rate
     spcm_dwSetParam_i32(self.hCard, SPC_CLOCKOUT,
                         0)  # Disables Clock Output
     check_clock = int64(0)
     spcm_dwGetParam_i64(self.hCard, SPC_SAMPLERATE,
                         byref(check_clock))  # Checks Sampling Rate
     verboseprint("Achieved Sampling Rate: ", check_clock.value)
Exemple #5
0
 def __init__(self, sample_length, amp=1.0):
     """
     Parameters
     ----------
     sample_length : int
         Sets the `SampleLength`.
     amp : float, optional
         Amplitude of waveform relative to maximum output voltage.
     """
     if sample_length % 32:
         verboseprint("Sample length is being truncated to align with 32 samples.")
     self.SampleLength = int(sample_length - sample_length % 32)
     self.Amplitude    = amp
     self.PlotObjects  = []
     self.Latest       = False
     self.FilePath     = None
     self.DataPath    = ''
Exemple #6
0
    def stabilize_intensity(self, wav, cam=None, which_cam=None):
        """ Balances power across traps.

        Applies an iterative update to the magnitude vector
        (corresponding to the trap array) upon image analysis.
        Converges to homogeneous intensity profile across traps.

        Example
        -------
        You could access this algorithm
        by passing a waveform object::

            myWave = Superposition([79, 80, 81])  # Define a waveform
            hCard.stabilize_intensity(myWave)  # Pass it into the optimizer

        or through the :doc:`GUI <../how-to/gui>`, offering camera view during the process::

            # Define a wave & load the board memory.
            hCard.wiggle_output(self, cam=True)
            # Use button on GUI

        Parameters
        ----------
        wav : :class:`~wavgen.waveform.Superposition`
            The waveform object whose magnitudes will be optimized.
        which_cam : bool, optional
            `True` or `False` selects Pre- or Post- chamber cameras respectively.
        cam : :obj:`instrumental.drivers.cameras.uc480`
            The camera object opened by :obj:`instrumental` module.
        """
        assert isinstance(
            wav, Superposition
        ), "Only Superpositions of pure tones can be optimized!"

        if cam is None:  # If we're not in GUI mode
            cam = self._run_cam()  # Retrieves a cam
            which_cam = 0
            self.load_waveforms(wav)
            self.wiggle_output(block=False)  # Outputs the given wave

        L = 0.2  # Correction Rate
        mags = wav.get_magnitudes()
        ntraps = len(mags)
        step_num, rel_dif = 0, 1
        while step_num < 5:
            step_num += 1
            verboseprint("Iteration ", step_num)

            trap_powers = analyze_image(which_cam, cam, ntraps, step_num)

            mean_power = trap_powers.mean()
            rel_dif = 100 * trap_powers.std() / mean_power
            verboseprint(f'Relative Power Difference: {rel_dif:.2f} %')

            ## Chain of performance thresholds ##
            if rel_dif < 0.1:
                debugprint("WOW")
                break
            elif rel_dif < 0.36:
                L = 0.001
            elif rel_dif < 0.5:
                L = 0.01
            elif rel_dif < 2:
                L = 0.05
            elif rel_dif < 5:
                L = 0.1

            deltaM = [(mean_power - P) / P for P in trap_powers]
            dmags = [L * dM / sqrt(abs(dM)) for dM in deltaM]
            wav.set_magnitudes(np.add(mags, dmags))
            self._update_magnitudes(wav)

        for i in range(5):
            if rel_dif > 0.5:
                break
            sleep(2)

            # im = np.zeros(cam.latest_frame().shape)
            # for _ in range(10):
            #     imm = cam.latest_frame()
            #     for _ in range(9):
            #         imm = np.add(imm, cam.latest_frame())
            #     imm = np.multiply(imm, 0.1)
            #
            #     im = np.add(im, imm)
            # im = np.multiply(im, 0.1)

            trap_powers = analyze_image(which_cam, cam, ntraps)
            dif = 100 * trap_powers.std() / trap_powers.mean()
            verboseprint(f'Relative Power Difference: {dif:.2f} %')

        plot_image(which_cam, cam.latest_frame(), ntraps)
        cam.close()
Exemple #7
0
    def wiggle_output(self, duration=None, cam=None, block=True):
        """ Performs a Standard Output for configured settings.

        Parameters
        ----------
        duration : int, float
            **straight mode only**
            Pass an integer to loop waveforms said number of times.
            Pass a float to loop waveforms for said number of milliseconds.
            Defaults to looping an infinite number of times.
        cam : bool, optional
            Indicates whether to use Camera GUI.
            *True* or *False* selects Pre- or Post- chamber cameras respectively.
        block : bool, optional
            Stops the card on function exit?

        Returns
        -------
        None
            WAVES! (This function itself actually returns void)
        """
        assert self.BufReady, "No Waveforms loaded to Buffer"
        assert not (duration
                    and self.Sequence), "Duration cannot be set for sequences."

        ## Timed or Looped mode determination ##
        if self.Sequence:
            verboseprint("Initiating Sequence start...")
        else:
            msg = "infinity..."
            if isinstance(duration, float):  # Timed Mode
                msg = str(duration / 1000) + " seconds..."
                spcm_dwSetParam_i32(self.hCard, SPC_TIMEOUT, int(duration))
            elif isinstance(duration, int):  # Looped Mode
                msg = str(duration) + " cycles..."
                spcm_dwSetParam_i64(self.hCard, SPC_LOOPS, int64(duration))
            else:  # Check for Invalid Option
                assert duration is None, "Invalid input for steps"
            verboseprint("Looping Signal for ", msg)

        ## Sets blocking command appropriately ##
        WAIT = M2CMD_CARD_WAITREADY if (duration and block
                                        and cam is None) else 0

        ## Start card, try again if clock-not-locked ##
        dwError = spcm_dwSetParam_i32(
            self.hCard, SPC_M2CMD,
            M2CMD_CARD_START | M2CMD_CARD_ENABLETRIGGER | WAIT)
        count = 0
        while dwError == ERR_CLOCKNOTLOCKED:
            verboseprint("Clock not Locked, giving it a moment to adjust...")
            count += 1
            sleep(0.1)
            self._error_check(halt=False, print_err=False)
            dwError = spcm_dwSetParam_i32(
                self.hCard, SPC_M2CMD,
                M2CMD_CARD_START | M2CMD_CARD_ENABLETRIGGER | WAIT)
            if count == 10:
                break

        ## Special Cases GUI/blocking ##
        if cam is not None:  # GUI Mode
            self._run_cam(cam)
            spcm_dwSetParam_i32(self.hCard, SPC_M2CMD, M2CMD_CARD_STOP)
        elif self.Sequence:
            verboseprint('Sequence running...')
        elif block:
            if not (self.Sequence
                    or duration):  # Infinite Looping until stopped
                easygui.msgbox('Stop Card?', 'Infinite Looping!')
            spcm_dwSetParam_i32(self.hCard, SPC_M2CMD, M2CMD_CARD_STOP)

        self._error_check()