|
1 | | -function [obj, varargout] = OpenEphys_Neuroblueprint(varargin) |
| 1 | +function [obj, varargout] = OpenEphys_Neuroblueprint_GUI(varargin) |
2 | 2 | % This is a class-based version of the GUI controller, structured similarly |
3 | 3 | % to runrats.m. It manages the experimental workflow through different |
4 | 4 | % 'actions' called via a switch statement. |
|
11 | 11 | % --- Boilerplate for class definition and action handling --- |
12 | 12 | obj = class(struct, mfilename); |
13 | 13 | varargout = {}; % Initialize varargout for actions that return values |
14 | | -if nargin==0 || (nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'empty')), |
| 14 | +if nargin==0 || (nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'empty')) |
15 | 15 | return; |
16 | | -end; |
17 | | -if isa(varargin{1}, mfilename), |
18 | | - if length(varargin) < 2 || ~ischar(varargin{2}), |
| 16 | +end |
| 17 | +if isa(varargin{1}, mfilename) |
| 18 | + if length(varargin) < 2 || ~ischar(varargin{2}) |
19 | 19 | error(['If called with a "%s" object as first arg, a second arg, a ' ... |
20 | 20 | 'string specifying the action, is required\n']); |
21 | 21 | else action = varargin{2}; varargin = varargin(3:end); |
22 | | - end; |
| 22 | + end |
23 | 23 | else |
24 | 24 | action = varargin{1}; varargin = varargin(2:end); |
25 | | -end; |
26 | | -if ~ischar(action), error('The action parameter must be a string'); end; |
| 25 | +end |
| 26 | +if ~ischar(action), error('The action parameter must be a string'); end |
27 | 27 | GetSoloFunctionArgs(obj); |
28 | 28 | % --- End of boilerplate --- |
29 | 29 |
|
|
35 | 35 | case 'init' |
36 | 36 | % This case is called once to create the GUI and initialize all parameters. |
37 | 37 |
|
| 38 | + % So that only the CPU-based software renderer instead of your graphics card |
| 39 | + opengl software; |
| 40 | + |
38 | 41 | % Start Bpod if not already running |
39 | 42 | if evalin('base', 'exist(''BpodSystem'', ''var'')') |
40 | 43 | if evalin('base', '~isempty(BpodSystem)'), newstartup; else, flush; end |
|
46 | 49 | SoloParamHandle(obj, 'oe_controller', 'value', []); |
47 | 50 | SoloParamHandle(obj, 'behav_obj', 'value', []); |
48 | 51 | SoloParamHandle(obj, 'blinking_timer', 'value', []); |
49 | | - SoloParamHandle(obj, 'monitor_timer', 'value', []); |
50 | 52 | SoloParamHandle(obj, 'current_params', 'value', []); |
51 | 53 | SoloParamHandle(obj, 'session_base_path', 'value', ''); |
52 | 54 | SoloParamHandle(obj,'is_running','value',0); |
|
88 | 90 | uicontrol(p2, 'Style', 'text', 'String', 'Project Name (Root):', 'Units', 'normalized', 'Position', [0.01, 0.85, 0.28, 0.1], 'HorizontalAlignment', 'right'); |
89 | 91 | handles.proj_edit = uicontrol(p2, 'Style', 'edit', 'String', 'sound_cat_rat', 'Units', 'normalized', 'Position', [0.3, 0.85, 0.65, 0.12]); |
90 | 92 | uicontrol(p2, 'Style', 'text', 'String', 'Subject ID:', 'Units', 'normalized', 'Position', [0.01, 0.7, 0.28, 0.1], 'HorizontalAlignment', 'right'); |
91 | | - handles.sub_edit = uicontrol(p2, 'Style', 'edit', 'String', '002', 'Units', 'normalized', 'Position', [0.3, 0.7, 0.65, 0.12]); |
| 93 | + handles.sub_edit = uicontrol(p2, 'Style', 'edit', 'String', '003', 'Units', 'normalized', 'Position', [0.3, 0.7, 0.65, 0.12]); |
92 | 94 | uicontrol(p2, 'Style', 'text', 'String', 'Local Path:', 'Units', 'normalized', 'Position', [0.01, 0.55, 0.28, 0.1], 'HorizontalAlignment', 'right'); |
93 | 95 | handles.local_edit = uicontrol(p2, 'Style', 'edit', 'String', 'C:\Ephys_Experiment_Data', 'Units', 'normalized', 'Position', [0.3, 0.55, 0.5, 0.12]); |
94 | 96 | handles.local_browse = uicontrol(p2, 'Style', 'pushbutton', 'String', 'Browse...', 'Units', 'normalized', 'Position', [0.81, 0.55, 0.16, 0.13], 'Callback', {@(h,e) feval(mfilename, obj, 'browse_path', 'local')}); |
|
267 | 269 | currentState.value = 'Stop'; |
268 | 270 | set(handles.control_button, 'String', 'Stop'); |
269 | 271 | feval(mfilename, obj, 'start_blinking'); |
270 | | - feval(mfilename, obj, 'start_monitoring'); |
271 | 272 |
|
272 | 273 | try |
273 | 274 | log_message(handles, 'Starting behavioral protocol...'); |
|
285 | 286 | handles = value(ui_handles); |
286 | 287 | log_message(handles, '--- STOP sequence initiated ---'); |
287 | 288 | feval(mfilename, obj, 'stop_blinking'); |
288 | | - |
| 289 | + behav_save_dir = fullfile(params.local_path, value(session_base_path), 'behav'); |
| 290 | + |
289 | 291 | try |
290 | 292 | log_message(handles, 'Ending behavioral session (saving data)...'); |
291 | | - feval(mfilename, obj, 'behav_control', 'end', params.protocol_name, params.behav_path); |
| 293 | + feval(mfilename, obj, 'behav_control', 'end', params.protocol_name, params.behav_path,behav_save_dir); |
292 | 294 | log_message(handles, 'Behavioral data saved successfully.'); |
293 | 295 | catch ME |
294 | 296 | log_message(handles, ['FATAL ERROR ending behavioral session: ' ME.message]); |
|
337 | 339 |
|
338 | 340 | case 'load_protocol_after_crash' |
339 | 341 | experimenter = args{1}; ratname = args{2}; protocol_name = args{3}; |
340 | | - video_save_dir = args{4}; behav_path = args{5}; |
| 342 | + behav_path = args{4}; |
341 | 343 | log_message(handles, ['Loading protocol: ' protocol_name]); |
342 | 344 | dispatcher('set_protocol', protocol_name); |
343 | 345 | rath = get_sphandle('name', 'ratname', 'owner', protocol_name); |
|
351 | 353 | if isfile(fullfile(temp_data_dir,temp_data_file)) |
352 | 354 | dispatcher('runstart_disable'); |
353 | 355 | load_soloparamvalues(ratname, 'experimenter', experimenter,... |
354 | | - 'owner', protobj, 'interactive', 0,'data_file',fullfile(temp_data_dir,temp_data_file)); |
| 356 | + 'owner', protocol_name, 'interactive', 0,'data_file',fullfile(temp_data_dir,temp_data_file)); |
355 | 357 | dispatcher('runstart_enable'); |
356 | 358 | end |
357 | | - % [sfile, ~] = SavingSection(protobj, 'get_set_filename'); |
358 | 359 | if ~dispatcher('is_running'), pop_history(class(protobj), 'include_non_gui', 1); feval(protocol_name, protobj, 'prepare_next_trial'); end |
359 | | - % feval(protocol_name, protobj, 'set_setting_params', ratname, experimenter, sfile, char(datetime('now')), video_save_dir); |
360 | | - |
| 360 | + |
361 | 361 | case 'crashed' |
362 | 362 | log_message(handles, '--- BEHAVIOR CRASH RECOVERY INITIATED ---'); |
363 | 363 | params = value(current_params); |
364 | | - feval(mfilename, obj, 'behav_control', 'load_protocol_after_crash', params.experimenter, params.rat_name, params.protocol_name, fullfile(params.local_path, value(session_base_path), 'behav'), params.behav_path); |
| 364 | + feval(mfilename, obj, 'behav_control', 'load_protocol_after_crash', params.experimenter, params.rat_name, params.protocol_name, params.behav_path); |
365 | 365 | feval(mfilename, obj, 'behav_control', 'run', params.protocol_name); |
366 | 366 | log_message(handles, '--- RECOVERY COMPLETE: Behavior protocol restarted ---'); |
367 | 367 |
|
|
375 | 375 |
|
376 | 376 |
|
377 | 377 | case 'end' |
378 | | - protocol_name = args{1}; root_dir = args{2}; |
| 378 | + protocol_name = args{1}; root_dir = args{2}; behav_copy_dir = args{3}; |
379 | 379 | log_message(handles, 'Stopping dispatcher...'); |
380 | 380 | dispatcher(value(behav_obj), 'Stop'); |
381 | 381 |
|
382 | 382 | %Let's pause until we know dispatcher is done running |
383 | | - set(value(stopping_complete_timer), 'Period', 2,'TimerFcn', {@(h,e) feval(mfilename, obj, 'behav_control','end_continued',protocol_name, root_dir)}); |
| 383 | + set(value(stopping_complete_timer), 'Period', 2,'TimerFcn', {@(h,e) feval(mfilename, obj, 'behav_control','end_continued',protocol_name, root_dir,behav_copy_dir)}); |
384 | 384 | %set(value(stopping_complete_timer),'TimerFcn',[mfilename,obj,'behav_control','(''end_continued'');']); |
385 | 385 | start(value(stopping_complete_timer)); |
386 | 386 |
|
387 | 387 | case 'end_continued' |
388 | 388 | %% end_continued |
389 | 389 | if value(stopping_process_completed) %This is provided by RunningSection |
390 | | - protocol_name = args{1}; root_dir = args{2}; |
| 390 | + protocol_name = args{1}; root_dir = args{2}; destination_path = args{3}; |
391 | 391 | stop(value(stopping_complete_timer)); %Stop looping. |
392 | 392 | is_running.value = 0; |
393 | 393 | feval(mfilename, obj, 'behav_control', 'send_empty_state_machine'); |
|
396 | 396 | feval(protocol_name, protobj, 'end_session'); |
397 | 397 | log_message(handles, 'Saving data and settings...'); |
398 | 398 | data_file = SavingSection(protobj, 'savedata', 'interactive', 0); |
399 | | - try, feval(protocol_name, protobj, 'pre_saving_settings'); catch, log_message(handles, 'Protocol does not have a pre_saving_settings section.'); end |
| 399 | + try |
| 400 | + feval(protocol_name, protobj, 'pre_saving_settings'); |
| 401 | + catch |
| 402 | + log_message(handles, 'Protocol does not have a pre_saving_settings section.'); |
| 403 | + end |
400 | 404 | [settings_file, ~] = SavingSection(protobj, 'get_set_filename'); |
401 | 405 | SavingSection(protobj, 'savesets', 'interactive', 0); |
402 | 406 | log_message(handles, 'Committing data and settings to SVN...'); |
403 | | - commit_to_svn(handles, data_file, root_dir); |
404 | | - commit_to_svn(handles, settings_file, root_dir); |
| 407 | + commit_to_svn(handles, data_file, settings_file, root_dir); |
405 | 408 | dispatcher('set_protocol', ''); |
| 409 | + dispatcher('close'); |
| 410 | + |
| 411 | + % wait sometime for dispatcher to stop using a timer object |
| 412 | + t = timer; |
| 413 | + t.StartDelay = 1; |
| 414 | + t.TimerFcn = @(~,~) log_message('waiting for before copying'); |
| 415 | + start(t);% Start the timer (it runs in the background) |
| 416 | + wait(t); % wait() pauses the script until the timer object is done. |
| 417 | + delete(t);% Clean up the timer from memory |
| 418 | + |
| 419 | + % Copy the data file to the folder saving ephys data |
| 420 | + [status, msg] = copyfile(data_file, destination_path); |
| 421 | + % Check if the copy was successful |
| 422 | + if status |
| 423 | + log_message(handles,'Data File copied successfully.'); |
| 424 | + else |
| 425 | + log_message(handles,['Error copying Data file: ' msg]); |
| 426 | + end |
| 427 | + |
406 | 428 | end |
407 | 429 |
|
408 | 430 | case 'create_svn_data_dir' |
|
492 | 514 | blinking_timer.value = []; |
493 | 515 | end |
494 | 516 | set(handles.control_button, 'BackgroundColor', [1, 0.4, 0.4]); |
495 | | - |
| 517 | + |
496 | 518 |
|
497 | 519 | case 'crash_detected' |
498 | 520 | % handles = feval(mfilename, obj, 'get_ui_handles'); |
|
0 commit comments