def _config_write_analog(self, channel, analog_event_handler=None, min_val=-10.0, max_val=10.0, **kwargs): """ Configure a channel or group of channels as an analog output Parameters)) ---------- channel: string a channel or group of channels that will all be written to at the same analog_event_handler: instance of events.EventDToAHandler an event handler for sending event information down an analog channel. Should have a channel attribute. min_val: float the minimum voltage that can be read max_val: float the maximum voltage that can be read Returns ------- True if configuration succeeded """ logger.debug("Configuring analog output on channel(s) %s" % str(channel)) task = nidaqmx.AnalogOutputTask() if self._analog_event_handler is None and \ analog_event_handler is not None: if not hasattr(analog_event_handler, "channel"): raise AttributeError( "analog_event_handler must have a channel attribute") channel = nidaqmx.libnidaqmx.make_pattern( [channel, analog_event_handler.channel]) logger.debug("Configuring digital to analog output as well.") self._analog_event_handler = analog_event_handler task.create_voltage_channel(channel, min_val=min_val, max_val=max_val) task.configure_timing_sample_clock(source=self.clock_channel, rate=self.samplerate, sample_mode="finite") self.tasks[channel] = task
# while simultaneously outputing a 1ms digital pulse every 5 ms (duty cycle 20%) # using correlated digital output based off the analog sample clock # need to start the dio task first! from __future__ import print_function from six.moves import input import numpy as np import nidaqmx nsamples = 1000 samplerate = 1000 adata = 9.95*np.sin(np.arange(nsamples,dtype=np.float64)*2*np.pi/nsamples) atask = nidaqmx.AnalogOutputTask() atask.create_voltage_channel('Dev1/ao0', min_val=-10.0,max_val=10.0) atask.configure_timing_sample_clock(rate=samplerate,sample_mode='finite', samples_per_channel=1000) atask.write(adata, auto_start=False) # ok that's tee'd up ddata = np.zeros(nsamples, dtype=np.uint8) ddata[0:nsamples:5]=1 dotask = nidaqmx.DigitalOutputTask() dotask.create_channel('Dev1/port0/line0', name='line0') #print("dotask info:", dotask.get_info_str(True)) print("atask info:", atask.get_info_str()) # note must use r'ao/SampleClock' (can't prefix with /Dev1/ dotask.configure_timing_sample_clock(source=r'ao/SampleClock',rate=1000,sample_mode='finite',samples_per_channel=1000) dotask.write(ddata, auto_start=False)
def __init__(self, config=None): # Load config # this sets self.config (the config attribute of our experiment class) to a dictionary containing all the values # in our config file. The keys of this dictionary correspond to the section headings in the config file, and # each value is another dictionary with keys that refer to the subheadings in the config file. This means you can # reference things in the dictionary by e.g. self.config['heading']['subheading'] with open(config) as f: self.config = yaml.load(f) self.quest_settings = self.config['quest_settings'] self.quest = None # Check quest numbers of trials if self.quest_settings['n_trials'] <= self.quest_settings['n_ignored']: raise ValueError( "Number of QUEST trials must be greater than the number of ignored trials" ) # ------------------------------------# # Subject/task information and saving # # ------------------------------------# # Enter subject ID and other information dialogue = gui.Dlg() dialogue.addText("Subject info") dialogue.addField('Subject ID') dialogue.addText("Task settings") dialogue.addField('Run QUEST', initial=True) dialogue.show() # check that values are OK and assign them to variables if dialogue.OK: self.subject_id = dialogue.data[0] self.run_quest = dialogue.data[1] else: core.quit() # Recode blank subject ID to zero - useful for testing if self.subject_id == '': self.subject_id = '0' # Folder for saving data self.save_folder = self.config['directories']['saved_data'] if not os.path.isdir(self.save_folder): os.makedirs(self.save_folder) self.save_path = '{0}/Subject{1}_data.csv'.format( self.save_folder, self.subject_id, data.getDateStr()) # Data to be saved self.data = dict( trial_number=[], # Trial number stimulation_level=[], # Detection probability voltage=[], # Actual voltage response=[], # Subject's response confidence=[], # Confidence rating detected=[], # Whether or not they detected the stimulus session=[], # Session number block=[], # Block number catch=[]) # Whether this was a catch trial # -----------------------# # Monitor & window setup # # -----------------------# monitor = monitors.Monitor('monitor', width=40.92, distance=74) monitor.setSizePix((1024, 768)) self.win = visual.Window( monitor=monitor, size=(1024, 768), fullscr=self.config['task_settings']['fullscreen'], allowGUI=False, color=rgb_convert((-1, -1, -1)), units='deg', colorSpace='rgb') self.win.mouseVisible = False # make the mouse invisible self.frame_rate = 60 # DAQ try: device = nidaqmx.libnidaqmx.Device( self.config['stimulation']['device']) device.reset() self.analogOutputTask = nidaqmx.AnalogOutputTask() self.analogOutputTask.create_voltage_channel('Dev1/ao0', min_val=-10.0, max_val=10.0) except: self.analogOutputTask = fakeAnalogOutputTask() # Keys used for making moves # self.response_keys = self.config['response keys']['response_keys'] # self.response_phases = self.config['response keys']['response_phases'] # levels of the tree io = launchHubServer() self.keyboard = io.devices.keyboard self.pain_key = self.config['response_keys']['pain_key'] self.no_pain_key = self.config['response_keys']['no_pain_key'] # Clock self.clock = core.Clock() # --------# # Stimuli # # --------# # Fixation cross self.fixation = visual.TextStim( win=self.win, height=self.config['stimuli']['fixation_size'], color='white', text="+") # Question mark for catch trials self.question_mark = visual.TextStim( win=self.win, height=self.config['stimuli']['question_mark_size'], color='white', text="?") self.instruction_text = visual.TextStim( win=self.win, height=self.config['stimuli']['text_size'], color='white', wrapWidth=30) self.instruction_text.fontFiles = [self.config['fonts']['font_path'] ] # Arial is horrible self.instruction_text.font = self.config['fonts']['font_name'] self.confidence_scale = ConfidenceScale(self.win, ymin=-5, ymax=5, width=8) # ---------------------- # # Stimulation parameters # # ---------------------- # # Default levels - used if calibration isn't performed self.detection_levels = [ self.quest_settings['default_p0'], self.quest_settings['default_p25'], self.quest_settings['default_p50'], self.quest_settings['default_p75'] ] # Voltage for practice self.practice_levels = [ self.config['task_settings']['low'], self.config['task_settings']['high'] ] # Voltage that shouldn't be exceeded self.abs_max_voltage = self.config['stimulation'][ 'absolute_maximum_voltage']