Basic API Usage in MATLAB

Intro running experiments in a local MATLAB session

When you start Zapit with start_zapit the MATLAB workspace will contain a variable called hZP. This serves as an API (Application Programming Interface) that allows controlling of almost all functions via the command line. For example, you can query which stimuli are loaded and whether Zapit is ready to deliver stimuli:

% Reports "true" and is ready to present stimuli
>> hZP.isReadyToStim

ans =
  logical
   1

% The stimulus config is located here 
>> hZP.stimConfig

ans = 
  stimConfig with properties:

            configFileName: 'C:\stim_configs\uniAndBilateral_5_conditions.yml'
            laserPowerInMW: 5
      stimModulationFreqHz: 40
             stimLocations: [1×5 struct]
    offRampDownDuration_ms: 250
               chanSamples: [2500×4×5 double]
      maxStimPulseDuration: 12.2000
           blankingTime_ms: 0.3000

% The stimulus config can be queried to return the number of conditions
>> hZP.stimConfig.numConditions

ans =
     5

Presenting a stimulus

The two main commands you will need for running experiments are sendSamples and stopOptoStim. sendSamples is so called because it transfers stimulus waveforms to the DAQ. The following code will send samples to the DAQ to stimulate one condition (e.g. one brain area bilaterally). It will start immediately because hardwareTriggered is set to false

hZP.sendSamples('conditionNum', 1, 'hardwareTriggered', false);

Stimulation begins and continues until stopOptoStim is run.

hZP.stopOptoStim

The stopOptoStim command will ramp down the laser power over a period defined in the stimulus config file. You can get help via the MATLAB command line e.g. help hZP.sendSamples

Presenting a randomly chosen stimulus

If you call sendSamples with the conditionNum undefined then a random stimulus is presented. The same stimulus will not be selected on two consecutive trials. The identity of the stimulus is returned as the first output argument of sendSamples

>> stim=hZP.sendSamples('hardwareTriggered', false)

stim =
     5

>> stim=hZP.sendSamples('hardwareTriggered', false)

stim =
     3

A simply toy scenario sees us present a small number of stimuli at random with each having a random duration:

numAreasToStim = length(hZP.stimConfig.stimLocations);

for ii=1:numAreasToStim
    % No stimulus condition defined so a random one chosen
    hZP.sendSamples('hardwareTriggered', false, 'verbose', true)
    pause(rand*2)
    hZP.stopOptoStim
    pause(0.3) % Because of https://github.com/Zapit-Optostim/zapit/issues/102
end

Presenting a control trial with the laser off

You can use the laserOn parameter to present a trial where the scanners move but the laser off:

hZP.sendSamples('laserOn',0)

If the value of laserOn is empty then a random laser on/off state is chose. The second output argument of sendSamples reports this state:

>> [S,L]=hZP.sendSamples('laserOn',0,'hardwareTriggered', false); disp([S,L])
     3     0

>> [S,L]=hZP.sendSamples('laserOn',0,'hardwareTriggered', false); disp([S,L])
     4     0

>> [S,L]=hZP.sendSamples('laserOn',0,'hardwareTriggered', false); disp([S,L])
     2     1

Logging stimuli

In a real experiment you will want to know which stimuli were presented when. To achieve this, set an "experiment path" in Zapit, the identity of presented stimuli will be logged to a file, along with all additional relevant information such as the laser on/off state. You can either set the experiment path in the GUI or at the command line by assigning a path to the hZP.experimentPath variable. If the variable is empty no logging takes place. If you run sendSampleswith logging set to false then also no logging takes place.

Precise control of stimulus timing

In the above examples stimuli started immediately because hardwareTriggered was always set to false and were terminated by stopOptoStim. The timing of events is therefore coarse. To present stimuli more accurately you can trigger them using a TTL line. By default you will connect port PFI0 on the Zapit NI DAQ to your trigger source. Stimulus presentation then begins when a TTL pulse is received. The following example uses code in the zapit\examples\externalTrigger folder and assumes you have a second DAQ called Dev2 with its port0/line0 connected to the Zapit PFI0 terminal

>> auxDAQ = connectAuxDaq('Dev2'); % replace by your DAQ ID name
>> makeTTLpulse(D) % sends a TTL pulse
>> hZP.sendSamples('conditionNum', 1);

%% Nothing happens until a TTL pulse is sent

>> makeTTLpulse(D) % send a TTL pulse to start the stimulation

%% Wait a while then stop the stimulation at the command line

>> hZP.stopOptoStim

In the above example we tie stimulus onset to a TTL trigger. Following on from this, we can also define a fixed stimulus duration thus:

>> hZP.sendSamples('conditionNum', 1, 'stimDurationSeconds', 2.25);

%% Nothing happens until a TTL pulse is sent

>> makeTTLpulse(D) % send a TTL pulse to start the stimulatio

%% A 2.25 second stimulus is presented followed by a rampdown

You can also define a delay between the onset of the stimulus and the trigger:

% Note in the following line we use abbreviated versions of the parameter 
% names and this still works.
>> hZP.sendSamples('cond', 1, 'stimDur', 2.25, 'startDelay', 0.5);

%% Nothing happens until a TTL pulse is sent

>> makeTTLpulse(D) % send a TTL pulse to start the stimulatio

%% 0.5 second delay then condition 1 is presented for  2.25 seconds then a rampdown

If stimulus duration is known in advance, it is preferable to use the stimDurationSeconds input argument to the sendSamplesmethod rather than a pause statement. The former is more accurate and has fewer failure points.

Last updated