Created
May 13, 2019 15:24
-
-
Save ClaudiuPapasteri/338703a73b0916dd125594d0d048e974 to your computer and use it in GitHub Desktop.
Sync Shimmer through key and time logger
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function SyncKeyTimeLog(logFileName) | |
% SyncKeyTimeLog(logFileName) | |
% | |
% Logs each key press using a figure call-back. The key name and press time | |
% are both recorded, with the most recent data being displayed on the | |
% figure. | |
% | |
% INPUTS: | |
% logFileName = string = save file name (optional) | |
% | |
% OUTPUTS: | |
% A .mat file with a data structure: KEY_PRESS_DATA | |
% | |
% KEY_PRESS_DATA.time = vector of the times when keys were pressed, in | |
% units of seconds, with 0.0 corresponding to the time when this function | |
% was called. | |
% | |
% KEY_PRESS_DATA.clock = vector of the times when keys were pressed, in | |
% machine time | |
% | |
% KEY_PRESS_DATA.keyName = cell array of the names of the keys that were | |
% pressed, matching one to one with the time data. | |
% | |
% USAGE: | |
% Calling this function will start a timer (with tic) and then write the | |
% name of each key that is pressed, along with the time to a data | |
% structure. | |
% | |
% The most recent data is copied to the figure, for user feedback | |
% | |
% Data logging is stopped by pressing the excape key or by | |
% closing the figure window. Once this occurs, a dialogue box will pop up | |
% to confirm the file save operation (to prevent accidentally overwriting | |
% old data), and change the save name if desired. | |
% | |
% NOTES: | |
% The figure is set to be in "modal" style which forces it to the top of | |
% all other windows. This is done to prevent missing keystrokes. This | |
% behavior can be changed by simply finding and removing the line: | |
% >> KEY_LOG_FIG.WindowStyle = 'modal'; | |
% | |
% Shimmer NOTES: | |
% Convert timetamp unix -> object datetime ... time zone Bucharest = UTC+3 hours | |
% numtime derived for Bucharest (+1080000 means 3 hours) and transform in numTime | |
% Time1 = ( TimeStamp + 10800000 ) / 86400000 + 719529; | |
% % # == datenum(1970,1,1) ... +10800 is Bucharest time offset for dif time zone | |
% Time2 = datestr(Time1, 'dd/mm/YYYY HH:MM:SS.FFF'); | |
% % transform in human readable Bucharest time | |
global KEY_PRESS_DATA DATA_LOG_INDEX DATA_LOG_LENGTH | |
global SAVE_FILE_NAME KEY_LOG_FIG TEXT_HANDLE | |
if nargin == 0 | |
logFileName = 'M2_ID.mat'; | |
end | |
% Initialize data logging: | |
DATA_LOG_LENGTH = 100; | |
KEY_PRESS_DATA.keyName = cell(DATA_LOG_LENGTH, 1); | |
KEY_PRESS_DATA.time = zeros(DATA_LOG_LENGTH, 1); | |
KEY_PRESS_DATA.clock = zeros(DATA_LOG_LENGTH, 1); | |
DATA_LOG_INDEX = 1; | |
SAVE_FILE_NAME = logFileName; | |
% Create a new figure to use for call-backs | |
KEY_LOG_FIG = figure(); | |
% Register callbacks with the figure | |
KEY_LOG_FIG.KeyPressFcn = @keyCallback; % Assign the callback for the arrow keys | |
KEY_LOG_FIG.DeleteFcn = @stopLoggingData; | |
% Force the window to be on top (avoid missing key presses); | |
KEY_LOG_FIG.WindowStyle = 'modal'; | |
% Set parameters for annotations on the figure | |
dim1 = [.1 .1 .3 .3]; | |
str1 = 'Log: Any Key'; | |
dim2 = [.8 .1 .3 .3]; | |
str2 = 'Exit: Esc'; | |
% Put text on the figure for feed-back: | |
TEXT_HANDLE = text(0.3,0.8,{'',''}); axis off; | |
annotation('textbox', dim1, 'String', str1, 'FitBoxToText', 'on'); | |
annotation('textbox', dim2, 'String', str2, 'FitBoxToText', 'on'); | |
TEXT_HANDLE.FontSize = 16; | |
% Start a timer | |
tic; | |
end | |
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~% | |
function keyCallback(~,event) | |
global KEY_PRESS_DATA DATA_LOG_INDEX DATA_LOG_LENGTH | |
global KEY_LOG_FIG TEXT_HANDLE | |
if strcmp('escape',event.Key) % Escape key = stop logging data | |
close(KEY_LOG_FIG); | |
else | |
% Allocate more memory if necessary | |
if DATA_LOG_INDEX > DATA_LOG_LENGTH | |
KEY_PRESS_DATA.time = ... | |
[KEY_PRESS_DATA.time; zeros(size(KEY_PRESS_DATA.time))]; | |
KEY_PRESS_DATA.clock = ... | |
[KEY_PRESS_DATA.clock; zeros(size(KEY_PRESS_DATA.clock))]; | |
KEY_PRESS_DATA.keyName = ... | |
[KEY_PRESS_DATA.keyName; cell(size(KEY_PRESS_DATA.keyName))]; | |
DATA_LOG_LENGTH = length(KEY_PRESS_DATA.time); | |
end | |
% Log the key press | |
timeNow = toc; | |
clockNow = now; | |
keyName = event.Key; | |
KEY_PRESS_DATA.time(DATA_LOG_INDEX) = timeNow; | |
KEY_PRESS_DATA.clock(DATA_LOG_INDEX) = clockNow; | |
KEY_PRESS_DATA.keyName{DATA_LOG_INDEX} = keyName; | |
DATA_LOG_INDEX = DATA_LOG_INDEX + 1; | |
% Put most recent data on the figure for the user: | |
TEXT_HANDLE.String{1} = sprintf('Time: %4.4f, ',timeNow); | |
TEXT_HANDLE.String{2} = ['Clock: ' datestr(clockNow,'HH:MM:SS.FFF')]; | |
TEXT_HANDLE.String{3} = ['Key Name: ' keyName]; | |
end | |
end | |
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~% | |
function stopLoggingData(~,~) | |
global KEY_PRESS_DATA DATA_LOG_INDEX DATA_LOG_LENGTH | |
global SAVE_FILE_NAME KEY_LOG_FIG TEXT_HANDLE | |
% Remove extra memory: | |
KEY_PRESS_DATA.time(DATA_LOG_INDEX:end) = []; | |
KEY_PRESS_DATA.clock(DATA_LOG_INDEX:end) = []; | |
KEY_PRESS_DATA.keyName(DATA_LOG_INDEX:end) = []; | |
% Ask user to confirm file save/overwrite (file name can be optionally passed to function): | |
answer = inputdlg({'Save file:'},'KeyLogger',1,{SAVE_FILE_NAME}); | |
if ~isempty(answer) % Set name | |
SAVE_FILE_NAME = answer{1}; | |
end | |
if exist(SAVE_FILE_NAME) == 2 % Check to avoid overiding an existing file | |
warning = questdlg('That file already exists! Append a .x (1) or Overwrite (2)?',... | |
'Warning',... | |
'Append x','Overwrite', 'Append x'); | |
switch warning | |
case 'Append x' | |
fileproblem = 1; | |
case 'Overwrite' | |
fileproblem = 2; | |
end | |
if fileproblem==2 | |
save(SAVE_FILE_NAME,'KEY_PRESS_DATA') | |
elseif fileproblem==1 | |
SAVE_FILE_NAME = ['X_' SAVE_FILE_NAME]; | |
save(SAVE_FILE_NAME,'KEY_PRESS_DATA'); | |
end | |
else | |
save(SAVE_FILE_NAME,'KEY_PRESS_DATA'); | |
end | |
% Release memory: | |
KEY_PRESS_DATA = []; | |
DATA_LOG_INDEX = []; | |
DATA_LOG_LENGTH = []; | |
SAVE_FILE_NAME = []; | |
KEY_LOG_FIG = []; | |
TEXT_HANDLE = []; | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment