예제 #1
0
파일: GVS.py 프로젝트: NNiehof/TimetraceSVV
    def connect(self, physical_channel_name, **timing_args):
        """
        Establish connection with NIDAQ apparatus. A virtual output channel
        and data stream writer are created.

        :param physical_channel_name: (str or list of str) name of output
        port on NIDAQ (to see available channel names, open NI MAX
        (software included with driver installation) and look under
        "Devices and Interfaces").
        The name might look something like "cDAQ1Mod1/ao0".
        **timing_args : keyword arguments from
        nidqamx.task.timing.cfg_samp_clk_timing.
        :return: True if connection was successful, otherwise False.
        """
        # check for multiple channels
        if isinstance(physical_channel_name, str):
            self.multiple_channels = False
            self.n_channels = 1
        elif isinstance(physical_channel_name, list):
            self.multiple_channels = True
            self.n_channels = len(physical_channel_name)
        else:
            self.logger.error("GVS.connect: please specify a valid "
                              "physical channel name.")

        try:
            if self.multiple_channels:
                # connect multiple analog output channels
                for chan_name in physical_channel_name:
                    self.add_ao_channel(chan_name)
                # config timing
                if "rate" not in timing_args:
                    rate = 1e3
                    self.task.timing.cfg_samp_clk_timing(rate, **timing_args)
                else:
                    self.task.timing.cfg_samp_clk_timing(**timing_args)
                # create output stream writer
                self.writer = stream_writers.AnalogMultiChannelWriter(
                    self.task.out_stream, auto_start=True)
            else:
                # connect single analog output channel
                self.add_ao_channel(physical_channel_name)
                # config timing
                if "rate" not in timing_args:
                    rate = 1e3
                    self.task.timing.cfg_samp_clk_timing(rate, **timing_args)
                else:
                    self.task.timing.cfg_samp_clk_timing(**timing_args)
                # create output stream writer
                self.writer = stream_writers.AnalogSingleChannelWriter(
                    self.task.out_stream, auto_start=True)

            logging.info("GVS task and channel created")
        except nidaqmx.errors.DaqError as err:
            self.logger.error("DAQmx error: {0}".format(err))
            return False

        self.logger.info("GVS task started")
        return True
예제 #2
0
    def run(self):
        self.parent.btn_run.setDisabled(True)

        self.directory()
        samples, channels, frequency = self.sequence()

        samples = np.delete(samples, 0, 0)
        samples = np.delete(samples, 0, axis=1)

        if len(samples) == (self.parent.table.columnCount() - 3):

            while self.parent.status_button == True:

                print samples

                self.parent.wait_time = int((1.0 / frequency) *
                                            len(samples[0]) + 1)
                print(samples)
                task = nidaqmx.Task()

                for channel in channels:
                    task.ao_channels.add_ao_voltage_chan('{0}'.format(
                        channel[1]))

                task.timing.cfg_samp_clk_timing(
                    rate=frequency,
                    sample_mode=nidaqmx.constants.AcquisitionType.FINITE,
                    samps_per_chan=len(samples[0]))

                write = stream_writers.AnalogMultiChannelWriter(
                    task.out_stream, auto_start=True)
                inicio = time.time()

                write.write_many_sample(samples, timeout=self.parent.wait_time)

                task.wait_until_done(timeout=self.parent.wait_time)
                task.stop()
                task.close()
                self.write_number()
                self.parent.shot_number()
                fim = time.time()
                print("elapsed time {0} seconds".format(fim - inicio))
                #print(len(samples[0]))
                self.parent.btn_run.setDisabled(False)

            self.parent.validation = True
            print('done')
            self.terminate()

        else:
            self.parent.validation = False
            self.parent.btn_run.setDisabled(False)
            self.parent.btn_autorun.setDisabled(False)
            self.terminate()
예제 #3
0
    def open(self):
        # AI
        self.t_in = {}

        for c in self.ai_chan_list:
            kwargs = dict(c)
            kwargs.pop("name", None)
            kwargs.pop("type", None)
            if c['type'] == 'voltage':
                kwargs['max_val'] = kwargs.get('max_val', 5)
                kwargs['min_val'] = kwargs.get('min_val', 0)
            for k in kwargs:
                if isinstance(kwargs[k], str):
                    if k == "thermocouple_type":
                        kwargs[k] = thermocouple_type[kwargs[k]]
                    elif k == "units":
                        kwargs[k] = units[kwargs[k]]
            if not c['type'] in self.t_in:
                self.t_in[c['type']] = nidaqmx.Task()
            try:
                getattr(self.t_in[c['type']].ai_channels,
                        "add_ai_%s_chan" % c['type'])(c['name'], **kwargs)
            except Exception:
                print("Invalid channel settings in nidaqmx:" + str(c))
                raise
        self.stream_in = {}
        for chan_type, t in self.t_in.items():
            self.stream_in[chan_type] = \
                stream_readers.AnalogMultiChannelReader(t.in_stream)
        # AO
        if self.ao_channels:
            self.t_out = nidaqmx.Task()
            self.stream_out = stream_writers.AnalogMultiChannelWriter(
                self.t_out.out_stream, auto_start=True)

        for c in self.ao_channels:
            kwargs = dict(c)
            kwargs.pop("name", None)
            kwargs.pop("type", None)
            kwargs['max_val'] = kwargs.get('max_val', 5)
            kwargs['min_val'] = kwargs.get('min_val', 0)
            self.t_out.ao_channels.add_ao_voltage_chan(c['name'], **kwargs)
        # DI
        if self.di_channels:
            self.t_di = nidaqmx.Task()
        for c in self.di_channels:
            kwargs = dict(c)
            kwargs.pop("name", None)
            kwargs.pop("type", None)
            self.t_di.di_channels.add_di_chan(c['name'], **kwargs)
        if self.di_channels:
            self.di_stream = stream_readers.DigitalMultiChannelReader(
                self.t_di.in_stream)

        # DO
        if self.do_channels:
            self.t_do = nidaqmx.Task()
        for c in self.do_channels:
            kwargs = dict(c)
            kwargs.pop("name", None)
            kwargs.pop("type", None)
            self.t_do.do_channels.add_do_chan(c['name'], **kwargs)
        if self.do_channels:
            self.do_stream = stream_writers.DigitalMultiChannelWriter(
                self.t_do.out_stream)
예제 #4
0
    return 0

# Now I start the actual PID loop        
with nid.Task() as write_task, nid.Task() as read_task:

    # First I configure the reading
    read_task.ai_channels.add_ai_voltage_chan(
        flatten_channel_string(channels_to_read),
        max_val=10, min_val=-10)
    reader = sr.AnalogMultiChannelReader(read_task.in_stream)
    
    # Now I configure the writing
    write_task.ao_channels.add_ao_voltage_chan(
            flatten_channel_string(channels_to_write),
            max_val=10, min_val=-10)
    writer = sw.AnalogMultiChannelWriter(write_task.out_stream)

    # source task.
    # Start the read and write tasks before starting the sample clock
    # source task.

    read_task.start()
    read_task.register_every_n_samples_acquired_into_buffer_event(
            20, # Every 20 samples, call callback function
            callback) 
    
    write_task.start()
    writer.write_many_sample(output_array)

    values_read = np.zeros((number_of_channels, samples_to_measure),
                           dtype=np.float64)
예제 #5
0
            min_val=-10,
            max_val=10,
            terminal_config=nidaqmx.constants.TerminalConfiguration.RSE)

    ao.timing.cfg_samp_clk_timing(
        RATE, sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS)
    ai.timing.cfg_samp_clk_timing(
        RATE,
        source='/Dev1/ao/SampleClock',
        sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS
    )  # synchronize our reading with when we write

    ao.out_stream.regen_mode = nidaqmx.constants.RegenerationMode.DONT_ALLOW_REGENERATION  # disable repeating old data, instead error if we run out
    ao.out_stream.output_buf_size = RATE  # one second of buffer. For latency, we want to keep this buffer as empty as possible.
    aow = stream_writers.AnalogMultiChannelWriter(
        ao.out_stream
    )  # Lets us stream data into the buffer and thus out onto the pin.
    aow.auto_start = False
    aow.write_many_sample(
        np.zeros((2, RATE // 4), dtype=np.float64), timeout=0
    )  # We need to write some data before we start the task, otherwise it complains

    do.write(True)  # SS high to sync with the slave
    ao.start()

    threading.Thread(target=saturate_zeros, args=(ao, aow),
                     daemon=True).start()

    time.sleep(
        0.1
    )  # Give startup ripples a moment to settle before starting to read data
    def __init__(self):
        #variables for file id 
        base_dir = 'C:/Users/inctel/Documents/ContrastDetectionTask/'

        expInfo = {'mouse':'Mfake',
        'date': datetime.datetime.today().strftime('%Y%m%d-%H_%M_%S'),
        'response_window': .5,
        'red_gain': 1.26,
        'blue_gain': 1.36,
        'red_volts':1.3,
        'blue_volts':1.4,

        }
        dlg = gui.DlgFromDict(dictionary=expInfo, title = 'Contrast Detection Task')
        if dlg.OK==False: core.quit()

        
        #stimulus variables
        tf = 2 #temporal frequency
        sf = .08
        sizes = [0,20]
        intensities = {}
        intensities[0] = [0,0]
        intensities[20] = [1,2,3,5,20,100]
        led_conds = ['none','square','noise']
        
        
        #task variables
        self.stim_delay = .2 #in s
        self.stim_time = .5 #in s
        self.response_window = expInfo['response_window']# in s
        self.isimin = 3 # in s
        self.isimax = 8 #in s
        self.grace_time = 1 #in s
        self.water_time = 100 #in ms
    
        #monitor variables
        monitor_width = 19.6 #in cm
        monitor_height = 9.5 #in cm

        #led variables
        
        expInfo['alphaRise'] = .001
        expInfo['alphaDecay'] = .005
        expInfo['tEPSG'] = .01
        expInfo['firingRate'] = 200 
        self.led_cond_function_key= {
            'none': self.gen_no_pulse,
            'square': self.gen_square_pulse,
            'noise': self.gen_synaptic_noise_stims
        }

        print('pre window generation')
        #initialize
        expInfo['monitor_dist']=10.47
        self.monitor = monitors.Monitor('BoxMonitor1', width=monitor_width,
         distance=expInfo['monitor_dist'])
        self.win = visual.Window(fullscr=True, monitor=self.monitor, 
            units="pix")
        
        print('generated window')
        FR = self.win.getActualFrameRate()
        expInfo['FR'] = FR 
        expInfo['monitor_height'] = monitor_height
        expInfo['water_time'] = self.water_time
        expInfo['position'] = np.array([0,0])
        expInfo['stim_time'] = self.stim_time
        

        expInfo['sf'] = sf #spatial frequency of grating
        expInfo['tf'] = tf #temporal frequency of greating
        expInfo['response_window'] = self.response_window
        expInfo['fs'] = 5000
        self.reverse_lick = True #if the lick is represented by low volts
        self.pix_per_deg = (self.monitor.getSizePix()[1]/
            (np.degrees(np.arctan(monitor_height/expInfo['monitor_dist']))))      
        
        print('set up some vars')
        
        #create trial conditions
        self.size_int_response = []
        #mult = math.ceil(500/(sum([len(intensities(s)) for s in sizes])*4))
        #print('I think mult should be ', mult)
        for temp in range(50):
            mini_size_int_response = []
            for _ in range(1): #how many blocks to shuffle in
                for s in sizes:
                    for ins in intensities[s]:
                        for led_cond in led_conds:
                            mini_size_int_response.append({'size':s,'intensity':ins,
                                'corr_response':ins>0,
                                'led_cond': led_cond})
            random.shuffle(mini_size_int_response)
            self.size_int_response += mini_size_int_response
        
        #and some more general variables
        self.phase_increment = tf/FR
        self.stim_on_frames = int(self.stim_time*FR)
        print('conditions genned')
        self.trial_timer = core.Clock()
        self.isi_timer = core.Clock()
        self.grating = visual.GratingStim(win=self.win, size=10*self.pix_per_deg, 
                pos=expInfo['position']*self.pix_per_deg,
            sf=sf/self.pix_per_deg,units='pix', ori=180+45, mask='circle')

        #maybe temp, add some display text
        self.text = visual.TextStim(win=self.win, text='startup', pos = [-250,-150],
            height=10,opacity=.35)
        
        #final setup
        self.filename = base_dir + expInfo['date']+'_' + expInfo['mouse']
        
        self.exp = data.ExperimentHandler('ContrastDetectionTask','v0',
            dataFileName = self.filename,
            extraInfo = expInfo)

        #set up the nidaq
        self.lick_daq = ni.Task()
        self.lick_daq.di_channels.add_di_chan('Dev1/Port1/Line0')
        self.lick_daq.start()
        print('daq launched')
        self.water_daq = ni.Task()
        self.water_daq.do_channels.add_do_chan('Dev1/Port1/Line2')

        self.led_daq = ni.Task()
        self.led_daq.ao_channels.add_ao_voltage_chan('Dev1/ao0')
        self.led_daq.ao_channels.add_ao_voltage_chan('Dev1/ao1')

        self.led_daq.timing.cfg_samp_clk_timing(rate=expInfo['fs'],
            sample_mode= ni.constants.AcquisitionType.FINITE, 
            samps_per_chan= int(np.floor(expInfo['fs']*(self.stim_time+self.response_window))))
        self.led_writer = stream_writers.AnalogMultiChannelWriter(self.led_daq.out_stream,
            auto_start=False)
        print('other daqs launched')
        self.fs=expInfo['fs']#TOFO: why here?
        self.run_blocks()
예제 #7
0
    def start_continuous_acq_n_gen(self):
        self._ao_task = ni.Task()
        self._ai_task = ni.Task()
        ai_args = {
            'min_val':
            self.ai_min_val,
            'max_val':
            self.ai_max_val,
            'terminal_config':
            ni.constants.TerminalConfiguration[self.ai_terminal_config]
        }

        self._ai_task.ai_channels.add_ai_voltage_chan(self.ai_a_name,
                                                      **ai_args)
        self._ai_task.ai_channels.add_ai_voltage_chan(self.ai_b_name,
                                                      **ai_args)

        self._ai_task.timing.cfg_samp_clk_timing(
            rate=self.ai_fs,
            sample_mode=ni.constants.AcquisitionType.CONTINUOUS,
            samps_per_chan=self._input_frame_len)

        self._ai_task.triggers.start_trigger.cfg_dig_edge_start_trig(
            "ao/StartTrigger", trigger_edge=ni.constants.Edge.RISING)

        # Below is a bit clumsy EAFP but we have to be careful writing to properties because they may or may not be
        # present depending on device type while the "double locking" system with both OVERRIDE and property needing
        # change requires user to really know what he is doing. In most cases if some control attribute is not
        # implemented in a device, it can work without issues just with the default settings though. On NI6211,
        # this code is debugged with, only the default output buffer had to be changed to prevent underflow at high
        # UBS data rates. I leave this code though for users to experiment in case of issues with other DAQ models.

        if self.ATTEMPT_OVERRIDE_DEFAULT_INPUT_BUFFER_SIZE:
            try:
                self._ai_task.in_stream.input_buf_size = self.sw_input_buffer_size
            except ni.errors.DaqError as exc:
                print(exc)
                print('ATTEMPT_OVERRIDE_DEFAULT_INPUT_BUFFER_SIZE failed')

        if self.ATTEMPT_OVERRIDE_DEFAULT_INPUT_OVERWRITE_BEHAVIOUR is True:
            try:
                if self.INPUT_OVERWRITE is False:
                    self._ai_task.in_stream.over_write = ni.constants.OverwriteMode.DO_NOT_OVERWRITE_UNREAD_SAMPLES
                elif self.INPUT_OVERWRITE is True:
                    self._ai_task.in_stream.over_write = ni.constants.OverwriteMode.OVERWRITE_UNREAD_SAMPLES
            except ni.errors.DaqError as exc:
                print(exc)
                print(
                    'ATTEMPT_OVERRIDE_DEFAULT_INPUT_OVERWRITE_BEHAVIOUR failed'
                )

        ao_args = {'min_val': self.ao_min_val, 'max_val': self.ao_max_val}

        ao_chan_a = self._ao_task.ao_channels.add_ao_voltage_chan(
            self.ao_a_name, **ao_args)
        ao_chan_b = self._ao_task.ao_channels.add_ao_voltage_chan(
            self.ao_b_name, **ao_args)

        if self.ATTEMPT_OVERRIDE_DEFAULT_USB_XFER is True:
            try:
                ao_chan_a.ao_usb_xfer_req_count = self.AO_USB_XFER_REQ_COUNT
                ao_chan_b.ao_usb_xfer_req_count = self.AO_USB_XFER_REQ_COUNT
                ao_chan_a.ao_usb_xfer_req_size = self.AO_USB_XFER_REQ_SIZE
                ao_chan_b.ao_usb_xfer_req_size = self.AO_USB_XFER_REQ_SIZE
            except ni.errors.DaqError as exc:
                print(exc)
                print('ATTEMPT_OVERRIDE_DEFAULT_USB_XFER failed')

        self._ao_task.timing.cfg_samp_clk_timing(
            rate=self.ao_fs,
            samps_per_chan=self._output_frame_len,  #TODO bug on dev1
            sample_mode=ni.constants.AcquisitionType.CONTINUOUS)

        if self.ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_REGENERATION_MODE is True:
            try:
                if self.ALLOW_OUTPUT_REGENERATION is False:
                    self._ao_task.out_stream.regen_mode = ni.constants.RegenerationMode.DONT_ALLOW_REGENERATION  # prevents DAQ card from repeating output, it just waits for more data to be added to the buffer- > but on cards that cant handle to automatically pause output generation when out of buffer this setting will case random and unexpected crash!
                elif self.ALLOW_OUTPUT_REGENERATION is True:
                    self._ao_task.out_stream.regen_mode = ni.constants.RegenerationMode.ALLOW_REGENERATION
            except ni.errors.DaqError as exc:
                print(exc)
                print(
                    'ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_REGENERATION_MODE failed')

        if self.ATTEMPT_OVERRIDE_DEFAULT_UNDERFLOW_BEHAVIOR_TO_PAUSE is True:
            try:
                self._ao_task.timing.implicit_underflow_behavior = ni.constants.UnderflowBehavior.AUSE_UNTIL_DATA_AVAILABLE  # SIC!
            except ni.errors.DaqError as exc:
                print(exc)
                print('Could not OVERRIDE_DEFAULT_UNDEFLOW_BEHAVIOR')
                if self._ao_task.out_stream.regen_mode == ni.constants.RegenerationMode.DONT_ALLOW_REGENERATION:
                    print(
                        'WARNING: Your device does not support pause in case of output underflow while auto '
                        'regeneration of the AO buffer is not allowed.\n  '
                        'In case of output buffer underflow due to system resources the application will crash!\n  '
                        'To prevent this warning and risk of crash its highly recommended to set _out_stream.regen_'
                        'mode to ALLOW_REGENERATION.\n  '
                        'This will allow output glitches in theory but will prevent '
                        'application from crashing on output buffer underflow.'
                    )

        if self.ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_BUFFER_SIZE is True:
            try:
                self._ao_task.out_stream.output_buf_size = self.sw_output_buffer_size
                # seems like buffer is not calculating correct and we must call out explicitly on NI6211.
                # Not setting this property leads to a chain of very confusing warnings/glitches.
            except ni.errors.DaqError as exc:
                print(exc)

        self._stream_reader = stream_readers.AnalogMultiChannelReader(
            self._ai_task.in_stream)
        self._stream_writer = stream_writers.AnalogMultiChannelWriter(
            self._ao_task.out_stream)

        # fill AO buffer with data
        self.function_gen.generate()
        buffer_frame = self.function_gen.output_frame

        for frames in range(self.CM_OUTPUT_FRAMES_PER_BUFFER - 1):  # TODO UGLY
            self.function_gen.generate()
            buffer_frame = np.append(buffer_frame,
                                     self.function_gen.output_frame,
                                     axis=1)

        self._ao_task.write(buffer_frame)

        self._ai_task.register_every_n_samples_acquired_into_buffer_event(
            self._input_frame_len, self.reading_task_callback)

        self._ao_task.register_every_n_samples_transferred_from_buffer_event(
            self._output_frame_len, self.writing_task_callback)

        self._ai_task.start()  # arm but do not trigger the acquisition
        self._ao_task.start(
        )  # trigger both generation and acquisition simultaneously

        self.cm_measurement_is_running = True