%% Export Continuous Data To Corpus Emulator % % % Import continuous data into MATLAB using TDTbin2mat
% Export to binary files that are read into Corpus as PZ5 data
% Use SynapseAPI to generate new recordings with this data
% Concatenate the resulting data sets into one master data structure
% %% Housekeeping % Clear workspace and close existing figures. Add SDK directories to MATLAB % path. close all; clear all; clc; [MAINEXAMPLEPATH,name,ext] = fileparts(cd); % \TDTMatlabSDK\Examples DATAPATH = fullfile(MAINEXAMPLEPATH, 'ExampleData'); % \TDTMatlabSDK\Examples\ExampleData [SDKPATH,name,ext] = fileparts(MAINEXAMPLEPATH); % \TDTMatlabSDK addpath(genpath(SDKPATH)); %% Importing the Data % This example assumes you downloaded our example data sets % () and extracted % it into the \TDTMatlabSDK\Examples\ directory. To import your own data, replace % |BLOCKPATH| with the path to your own data block. % % In Synapse, you can find the block path in the database. Go to Menu > History. % Find your block, then Right-Click > Copy path to clipboard. BLOCKPATH = fullfile(DATAPATH,'Algernon-180308-130351'); %% Setup the variables for the data you want to extract % We will extract a stream store and output it to a Mat file STORE = 'Wav1'; % the circuit loads and begins running before Synapse switches to record % mode, so add 5 seconds of zeros to the front of it to make sure we are % recording all of our data. PADDING = 5; %% Experiment setup % This example uses the '_Demo_TankReplayer' experiment included in the download. % In the RZ HAL, PortC0 is enabled as an input and its epoc store is set to % 'Full'. This is critical to capture when the PZ data is valid. This will % create the PC0_ epoc event that we can time filter on during extraction. EXPERIMENT = '_Demo_TankReplayer'; TARGET_DEVICE = 'PZ5'; % PZ5 or PZ2 if ~strcmp(EXPERIMENT(1:6), '_Demo_') error('Experiment name must start with _Demo_ to automatically import Corpus data') end % Connect to Synapse syn = SynapseAPI(); % Set appropriate scale factor depending on our device type if strcmpi(TARGET_DEVICE, 'PZ5') SCALE = 1e9 / 4; elseif strcmpi(TARGET_DEVICE, 'PZ2') || strcmpi(TARGET_DEVICE, 'PZ3') || strcmpi(TARGET_DEVICE, 'PZ4') SCALE = 1e9; end %% % Read the headers to see how much data we have heads = TDTbin2mat(BLOCKPATH, 'TYPE', {'streams'}, 'STORE', STORE, 'HEADERS', 1); % get the total data size first nchan = double(max(heads.stores.(STORE).chan)); npts = double(heads.stores.(STORE).size - 10); MAX_SAMPLES = 256e6 / 2; % Corpus can load up to 256M samples total. Cut it in half to be safe. % leave room for our digital trigger as well nsamples = npts * double(numel(heads.stores.(STORE).chan)) * (nchan+1) / nchan; FS = heads.stores.(STORE).fs; ZEROPAD = zeros(nchan, ceil(PADDING * FS)); % if it's too big, we need to split it up iter = ceil((nsamples + numel(ZEROPAD)) / MAX_SAMPLES); % figure out what T1 and T2 should be on each iteration T1 = 0; % subtract our pad off of it, plus a little extra to be safe DELTA = MAX_SAMPLES / FS / (nchan + 1) - (PADDING + 0.5); FOLDERNAME = EXPERIMENT(7:end); ROOT = sprintf('C:\\TDT\\Corpus\\Simulation Files\\Synapse Demos\\%s', FOLDERNAME); blockPaths = cell(1,iter); for ii = 1:iter % first set it to the default experiment syn.setCurrentExperiment('Experiment'); refreshExperiment = tic; % read our data into MATLAB and create MAT file for PZ5 emulated data data = TDTbin2mat(BLOCKPATH, 'TYPE', {'streams'}, 'STORE', STORE, 'HEADERS', heads, 'T1', T1, 'T2', T1 + DELTA); folder = fullfile(ROOT, 'PZ1'); mkdir(folder); OUTFILE = fullfile(folder, 'chan.mat'); arr = [ZEROPAD data.streams.(STORE).data] * SCALE; % log it DURATION = size(arr, 2) / FS; fprintf('Wrote %s to output file %s\n', STORE, OUTFILE); fprintf('Sampling Rate:\t%.6f Hz\n', FS); fprintf('Num Channels:\t%d\n', size(data.streams.(STORE).data, 1)); fprintf('Duration:\t\t%.1fs (includes padding)\n', DURATION); % make the digital input trigger that tells when the data is valid bits = [zeros(1, size(ZEROPAD, 2)) ones(1, size(data.streams.(STORE).data,2))]; clear data; save(OUTFILE, 'arr'); clear arr; % save the digital input trigger data into Corpus directory folder = fullfile(ROOT, 'RZ1'); mkdir(folder); OUTFILE = fullfile(folder, 'bits.i16'); fileID = fopen(OUTFILE,'w'); fwrite(fileID, bits, 'int16'); fclose(fileID); fprintf('Wrote Sync Bit0 to output file %s\n', OUTFILE); clear bits; % Reload your experiment to force Corpus to reload the new data % then to our experiment % make sure enough time has elapsed that Corpus detected the change while tic - refreshExperiment < 3 pause(.1); end % load our experiment so Corpus catches it syn.setCurrentExperiment(EXPERIMENT); disp('Wait until data has loaded into Corpus (estimated)') pause(max(DURATION/10, 5)) syn.setModeStr('Record'); fprintf('Wait until data has completely cycled through (%d seconds)\n', ceil(DURATION)) pause(PADDING); while syn.getSystemStatus.iRecordSecs < ceil(DURATION) pause(1) end % store this block name thisBlockPath = fullfile(syn.getCurrentTank, syn.getCurrentBlock); fprintf('Done recording into: %s\n', thisBlockPath) blockPaths{ii} = thisBlockPath; % get ready for next iteration syn.setModeStr('Idle'); T1 = T1 + DELTA; end %% Import the new data back into MATLAB % disp('Reading the data back into MATLAB') for ii = 1:numel(blockPaths) tempdata = TDTbin2mat(blockPaths{ii}, 'TYPE', {'epocs'}); % get just the epoc events % we just want the first valid epoc event tr = [tempdata.epocs.PC0_.onset(1); tempdata.epocs.PC0_.offset(1)]; % extract our data, just on that time range tempdata = TDTbin2mat(blockPaths{ii}, 'RANGES', tr); % your custom analysis code here end