Autogeneration of cycles is one of the more advanced and, consequently, more powerful features of Ephus. It is relatively straightforward to write a function to generate a cycle. There are essentially only two tasks that need to be done. First is to create a series of pulses and second is to map those pulses into a cycle. A new autogenerated cycle can be created using the following steps, including some finishing touches to make the function especially user-friendly:

  • Gather the necessary variables; these often include the pulseJacker handle and the required sampleRate.
mapperObj = getGlobal(progmanager, 'hObject', 'mapper', 'mapper');
sampleRate = getLocalBatch(progmanager, mapperObj, 'sampleRate');
pj = getGlobal(progmanager, 'hObject', 'pulseJacker', 'pulseJacker');
  • Identify the full path to the target pulseSet (the location in which the new pulses will be stored).
destDir = getDefaultCacheDirectory(progmanager, 'myCustomPulses');%Use a cached value, to reduce the need to prompt the user.
if strcmpi(destDir, pwd)
     destDir = getDefaultCacheDirectory(progmanager, 'pulseDir'); %Use the pulseEditor's cached directory if this function's cached value is just Matlab's current directory (the default).
end
destDir = uigetdir(destDir, 'Choose a pulseSet for the destination of new pulses.'); %Prompt the user to choose a directory, defaulting to the cached value.
if length(destDir) == 1
     if destDir == 0
          return; %The user has cancelled the directory selection, take that as a queue to quit the function completely.
     end
end

%Test that the directory is valid before proceeding.
if exist(destDir, 'dir')
     error('pulseDest must be a valid directory: ''%s'' does not exist.', destDir);
end
setDefaultCacheValue(progmanager, 'myCustomPulses', destDir); %Update the cached value, for the subsequent calls to this function.
[pulseDir, pulseSetName] = fileparts(destDir); %Hold on to these values for later use.
  • Create pulses, which will get re-used within a loop.
channel1Pulse = signalobject('Name', 'myCustomCycleChan1', 'repeatable', 0, 'sampleRate', sampleRate);
channel2Pulse = signalobject('Name', 'myCustomCycleChan2', 'repeatable', 0, 'sampleRate', sampleRate);
  • Configure the pulses, within a loop, and save them to the selected directory.
for i = 1 : 10
     set(channel1Pulse , 'Name', ['myCustomCycleChan1' num2str(i)]); %Update the pulse's name/number.
     set(channel2Pulse , 'Name', ['myCustomCycleChan2' num2str(i)]); %Update the pulse's name/number.
     %Set the pulse's values.
     dc(channel1Pulse , i);
     sin(channel1Pulse, i, 0, 1000, 0);
     %Now save the pulses.
     for signal = [channel1Pulse, channel2Pulse]
          fprintf(1, 'Writing pulse to disk - ''%s''...\n', get(signal, 'Name'));%Print an informative message for the user.
          saveCompatible(fullfile(destDir, [get(signal, 'Name') '.signal']), 'signal', '-mat');
     end
end
  • Pulse objects are pass-by-reference objects, and thus they represent a potential memory leak in Matlab. It is good practice to delete them when they are no longer needed.
delete(channel1Pulse);
delete(channel2Pulse);
  • Create a new cycle in the pulseJacker.
%This will prompt the user to name the cycle, and potentially overwrite an existing one.
if ~pj_new(pj)
     %The pj_new command was cancelled or failed. Don't go overwriting an existing cycle if someone cancelled.
     return;
end

%Make sure the pulse path matches where we just made new pulses.
pj_setPulsePath(pj, pulseDir);
fprintf(1, 'Creating associated cycle ''%s''...\n', getLocal(progmanager, pj, 'cycleName'));%Print a message for the user.

%Get the list of channels that are in the pulseJacker.
channels = getLocalGh(progmanager, pj, 'currentChannel', 'String');
  • Populate the new cycle, mapping the created pulses to the correct channels and cycle positions.
for i = 1 : 10
fprintf(1, 'Creating cycle position %s...\n', num2str(i) ); %Print a message for the user.

pj_newPosition(pj);%Create a new cycle position.
%Iterate over the channels, there may be configured channels that will not be used during this cycle.
for j = 1 : length(channels)
     fprintf(1, 'Configuring pulse for channel ''%s''...\n', channels{j});
          %Select the channel we want to edit.
          pj_currentChannel(pj, channels{j});
          %Set the pulseSet for this channel.
          pj_setPulseSetName(pj, pulseSetName);%pulseSetName was defined earlier, when selecting the pulse destination.
          %Depending on which channel we currently have selected, choose the appropriate pulse.
          %Only operate on the channels of interest.
          if endsWithIgnoreCase(channels{j}, ':myChannel1')
               pj_setPulseName(pj, ['myCustomCycleChan1', num2str(i)]);
          elseif endsWithIgnoreCase(channels{j}, ':myChannel2')
               pj_setPulseName(pj, ['myCustomCycleChan2', num2str(i)]);
          end
     end
end

%Make things nice for the user, so it's ready to go immediately.
pj_currentPosition(pj, 1);%Set the new cycle to the first position.
pj_currentChannel(pj, channels{1});%Set the new cycle to the first channel.
  • No labels