JA_SBJ_performance.m 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. function [Ob, Par] = JA_SBJ_performance(Par,Ob,arg,s)
  2. %%
  3. % if a standard trial --> set charger
  4. % set a frame counter
  5. % is it a catch trial? --> if yes set the set charge counter --> check if
  6. % it is below a low_threshold? --> output that no response has been provided within the time limits (1.0 + charge secs)
  7. % if charger is higher than low_threshold
  8. %
  9. %% set parameters
  10. [~,ifi_as] = JA_frames_function(Par.ifi, Par.ifi);
  11. [~,~,~,charge_ns] = JA_frames_function(Par.charge, Par.ifi);
  12. %% assign objects to tobj and tsens variables
  13. % prepare the piston final position
  14. player = arg.player;
  15. tmp_VBL_ball_changes_color = strcat('VBL_ball_changes_color_', player);
  16. tmp_VBL_ball_back_to_gray = strcat('VBL_ball_back_to_gray_', player);
  17. start_counting = Par.(tmp_VBL_ball_changes_color){Par.tr};
  18. target_object = strcat('piston_', player);
  19. [new_piston_dimensions] = JA_piston_sliding_final_dimension(Ob, target_object);
  20. % set the EEG trigger code value for the current trial
  21. piston_trigger_name = strcat(target_object, '_Trigger');
  22. value_hitting_piston = Par.final_design.(piston_trigger_name)(Par.tr);
  23. % set the target sensors to be checked
  24. sens = strcat('arduino_', arg.sensor);
  25. tsens = Ob.(sens); % piston_SBJ
  26. % set the position to extract after reading from arduino
  27. switch sens
  28. case 'arduino_CF_RISP'
  29. reading_from_arduino_position = 1;
  30. case 'arduino_SBJ_RISP'
  31. reading_from_arduino_position = 3;
  32. case 'arduino_SBJ_DCG'
  33. reading_from_arduino_position = 2;
  34. end
  35. % get baseline pressure
  36. baseline = Par.baseline{Par.tr}.(arg.sensor);
  37. % proportion of change from bs
  38. baseline_percentage = [0.05 1.4];
  39. % set valid response time window
  40. valid_response_window = [0.15 1] + Par.charge; % RT + charge delay
  41. tmp_turn = strcat(player, '_colors');
  42. correct_response = Par.final_design.(tmp_turn){Par.tr};
  43. switch correct_response
  44. case 'lift_color'
  45. charger_threshold = -charge_ns;
  46. case 'press_color'
  47. charger_threshold = charge_ns;
  48. case 'catch_color' % it does not matter which threshold is placed here
  49. charger_threshold = charge_ns;
  50. end
  51. charger = 0;% charger_threshold;
  52. RT = nan;
  53. %%
  54. % get timing at this point, after the color got gray again (0.0667 ms theoretically)
  55. initial_time_counting = Par.(tmp_VBL_ball_back_to_gray){Par.tr};
  56. % set stop signal
  57. done = 0;
  58. % set cycle counter
  59. t = 1;
  60. abstime(t) = initial_time_counting;
  61. % while the stop signal is off
  62. while (done == 0)
  63. % increase counter
  64. t = t+1;
  65. % read sensor status
  66. JA_inside_fun_READ_WRITE();
  67. % timestamp of first cycle is the initial timestamp
  68. abstime(t) = GetSecs;
  69. estimate(t) = abstime(t) - abstime(t-1);
  70. JA_inside_fun_CHARGER();
  71. JA_inside_fun_CHECK_CHARGER_STATUS();
  72. end
  73. %% hit the ball
  74. tmp_piston_name = strcat('VBL_piston_', player);
  75. Ob.(target_object).dimension = new_piston_dimensions;
  76. % print on front screen what is going on and get a VBL timing
  77. [Ob, Par]= JA_Load_Obj_On_Screen(Par, Ob);
  78. [Par.VBL] = Screen(Par.window, 'Flip');
  79. % get VBL of piston hitting the ball
  80. Par.(tmp_piston_name){Par.tr} = Par.VBL;
  81. % EEG trigger code for color change
  82. EEG_Trigger(Par.PP,Par.address,value_hitting_piston);
  83. %%
  84. tmp_name_RT = strcat(player, '_RT_tmp');
  85. tmp_name_performance = strcat(player, '_performance_Type');
  86. tmp_name_classification = strcat(player, '_classification');
  87. % when the while cycle has stopped
  88. Par.(tmp_name_RT){Par.tr} = RT;
  89. Par.(tmp_name_classification){Par.tr} = classification;
  90. Par.final_design.(tmp_name_performance){Par.tr} = Par.(tmp_name_classification){Par.tr};
  91. %% read and write
  92. function [] = JA_inside_fun_READ_WRITE()
  93. % WRITE ON THE SERIAL AND GET VALUE FROM ARDUINO
  94. tmp_value = scrittura(s);
  95. % slpit the 3 values that are read from the three pins in arduino
  96. tmp2 = (strsplit(tmp_value, '_'));
  97. % assign the read value to the tsarget sensor tsens
  98. tsens.val = str2double(tmp2{reading_from_arduino_position});
  99. end
  100. %% check if the pressure has changed from the baseline and charge the charger in case
  101. function []= JA_inside_fun_CHARGER()
  102. % if the detected pressure is within baseline_percentage values (nothing has changed)
  103. if tsens.val >= baseline_percentage(1)*baseline && tsens.val <= baseline_percentage(2)*baseline;
  104. charger_tmp = 0; % caricatore rimane a zero
  105. else % if a significant deviation from baseline has been detected
  106. % in case the pressure is increasing
  107. if tsens.val > baseline_percentage(2)*baseline
  108. charger_tmp = estimate(t);%sum(length(t-increase+1:t));
  109. end
  110. % in case pressure is decreasing
  111. if tsens.val < baseline_percentage(1)*baseline
  112. charger_tmp = -estimate(t);
  113. end
  114. end
  115. % cumulatively charge the variable charger until it reaches charger_threshold;
  116. % note that if the charge_threshold is positive(negative) and SBJ is (pressing)lifting, the charger will tend towards 0
  117. % if no significant change from baseline is detected, charger will
  118. % remain at the previous level
  119. charger = charger + charger_tmp;
  120. % Set a maximum/minimum
  121. % In case final_count_down goes above the max or below the min, set
  122. % it either to the max or to the min
  123. % if charger >= charger_threshold;
  124. % charger = charger_threshold;
  125. % end
  126. %
  127. % if charger <= charger_threshold;
  128. % charger = charger_threshold;
  129. % end
  130. if strcmp(Par.final_design.CF_colors{Par.tr}, 'catch_color') && abs(charger)>Par.threshold_catch_response;
  131. % in a catch trial, if SBJ produces even a brief response that does not charge the charger completely
  132. % the charger will be set to maximum/minimum --> the script
  133. % detects a response
  134. charger = charger_threshold;
  135. end
  136. end
  137. %% check charger status and decide what to do based on it
  138. function [] = JA_inside_fun_CHECK_CHARGER_STATUS()
  139. % get time from color change
  140. getTime = GetSecs - start_counting;
  141. % if pressed enough time in a press trial
  142. if charger_threshold > 0 && (charger >= charger_threshold)
  143. if getTime <= valid_response_window(1) % response too fast...
  144. disp('pressed too fast')
  145. RT = getTime;
  146. classification = 'out_fast_press';
  147. done = 1;
  148. else
  149. disp('pressed enough time in a press trial')
  150. RT = getTime;
  151. classification = 'press';
  152. done = 1;
  153. end
  154. end
  155. % if lifted enough time in a lift trial
  156. if charger_threshold < 0 && (charger <= charger_threshold)
  157. if getTime <= valid_response_window(1) % response too fast...
  158. disp('lifted too fast')
  159. RT = getTime;
  160. classification = 'out_fast_lift';
  161. done = 1;
  162. else
  163. disp('lifted enough time in a lift trial')
  164. RT = getTime;
  165. classification = 'lift';
  166. done = 1;
  167. end
  168. end
  169. % if no (correct) response has been provided within the time limits...
  170. if getTime >= valid_response_window(2) % response too slow, or catch trials
  171. disp('no (correct) response provided')
  172. RT = getTime;
  173. classification = 'no_response';
  174. done = 1;
  175. end
  176. % for warming_up failed trials...
  177. if charger_threshold > 0 && (charger <= -Par.threshold_catch_response) && strcmp(Par.relationship, 'warming_up')
  178. RT = getTime;
  179. classification = 'wrong_response';
  180. done = 1;
  181. end
  182. if charger_threshold < 0 && (charger >= Par.threshold_catch_response) && strcmp(Par.relationship, 'warming_up')
  183. RT = getTime;
  184. classification = 'wrong_response';
  185. done = 1;
  186. end
  187. end
  188. end