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.