function [forces]=ISP_MoBi_sequence(contraction_task, data_subject, volume, forces, bl) % the script is identical to ISP_MoBi_sequence_MEP with the exception of no % force estimation and only MEP blocks (so there are only TEP blocks). % refer to the ISP_MoBi_sequence_MEP for comments max_force_left = forces.max_force_left; max_force_right = forces.max_force_right; cd 'C:\Users\neuro\Desktop\script_mobi_da_commentare' sca; close all; %% % consider left hand state switch contraction_task{1,2} % force as a proportion of the outer circle... case 'Contratta' LEFT = [0.2 0.4]; istruzione_sx = 'Mantieni\nil cerchietto\nverde'; case 'Rilassata' LEFT = [0 0.01]; istruzione_sx = 'Rilassa' end % consider right hand state switch contraction_task{1,3} case 'Contratta' RIGHT = [0.2 0.4]; istruzione_dx = 'Mantieni\nil cerchietto\nverde'; case 'Rilassata' RIGHT = [0.0 0.01]; istruzione_dx = 'Rilassa' end %% specify trigger number switch contraction_task{1,1} case 'Mono_AP' TMS_trigger = 3; case 'Mono_PA' TMS_trigger = 5; case 'Mono_LM' TMS_trigger = 7; case 'Bi_PA_contracted' TMS_trigger = 160; case 'Bi_AP' TMS_trigger = 130; case 'Bi_PA' TMS_trigger = 150; case 'Bi_LM' TMS_trigger = 170; end %% % as a proportion to y axis... outer_dimension = 0.4; inner_dimensionL = LEFT(1); middle_dimensionL = LEFT(2); inner_dimensionR = RIGHT(1); middle_dimensionR = RIGHT(2); inner_force_limit_propL = inner_dimensionL; outer_force_limit_propL = middle_dimensionL; inner_force_limit_propR = inner_dimensionR; outer_force_limit_propR = middle_dimensionR; outer_circle_color = [1 1 1];%[0 0 0];% middle_circle_color = [0.5 0.5 0.5]; inner_circle_color = [0 0 0]; variable_circle_colorL = [0 1 0]; variable_circle_colorR = [0 1 0]; variable_circle_thickness = 5; force_steps = 500; num_trials = 40; estimation_time = 10; %secs time_x_avg = 0.5; % secs %% DO you want to tinker with small screen? tinker = 0; HideCursor %% SCREEN SETTING [window, misure_schermo, screenNum, CenterX, CenterY, ifi] = MoBi_Screen_Settings_Brescia(tinker); %MoBi_Screen_Settings_Brescia; %proporzioni_schermo = misure_schermo(4)/misure_schermo(3); %% delete(instrfindall); clear s %Set up the serial port s = serial('COM5'); set(s, 'BaudRate', 115200); % set BaudRate to 115200 (as in Arduino!!!!!) % open it fopen(s); WaitSecs(2); for d = 1:2 MoBi_scrittura(s); end %% [ifi_af, ifi_as, ifi_nf, ifi_ns] = MoBI_frames_Brescia(ifi, ifi); [onesec_af, onesec_as, onesec_nf, onesec_ns] = MoBI_frames_Brescia(1, ifi); %% parallel port init ioObj = io64; status = io64(ioObj); address = hex2dec('DFB8'); io64(ioObj, address ,0); %% delay_after_TMS = 0.4; TMS_extremes = [4.4 6.4]-delay_after_TMS; TMS_interval_tmp = (TMS_extremes(2) - TMS_extremes(1))*rand(num_trials,1)+TMS_extremes(1); [TMS_int_af, TMS_int_as, TMS_int_nf, TMS_int_ns] = MoBI_frames_Brescia(TMS_interval_tmp, ifi); %% the systems outputs a "-1/force" function % --> set the max of the function to max_force and the min to 0 % in steps of 500 values of forces (this can be changed) x = linspace(1,10,force_steps); % produce the shape funz_tmp = (-1./x)+1; % the shape is morphed so that it goes from 0 to 1 and multuplied by % max_force funzL = (funz_tmp./(funz_tmp(end)))*max_force_left; funzR = (funz_tmp./(funz_tmp(end)))*max_force_right; % this is the linear function with range [0 max_force] which will be % helpful afterwards to linearize the voltage read linearizeL = linspace(0, max_force_left, force_steps); linearizeR = linspace(0, max_force_right, force_steps); %% SET ALL THE VISUALS on the LEFT % proportion with respect to the entire screen set_proportion_of_diameter_outer_circleL = outer_dimension; prop_diameter_outer_circleL = set_proportion_of_diameter_outer_circleL; % transform proportions to actual pixels --> we get dimaeter of outer % circle in pixels dimensions_outer_circleL = MoBi_prop2dim(misure_schermo, 0, prop_diameter_outer_circleL); % same procedure for inner and middle circle calculated on the basis of the outer % circle prop_diameter_inner_circleL = inner_dimensionL*prop_diameter_outer_circleL; dimensions_inner_circleL = MoBi_prop2dim(misure_schermo, 0, prop_diameter_inner_circleL); prop_diameter_middle_circleL = middle_dimensionL*prop_diameter_outer_circleL; dimensions_middle_circleL = MoBi_prop2dim(misure_schermo, 0, prop_diameter_middle_circleL); %% generate a structure for the LEFT circle with the features of the circle as fields % we have two objsect now...place the left one on the first quarter of the % screen length, the other on the last quarter first_quarter = 3*misure_schermo(3)/8; last_quarter = 5*misure_schermo(3)/8; % ...color ObL.outer_circle.color = outer_circle_color; % ...diameter ObL.outer_circle.dimension = [0 0 dimensions_outer_circleL(2) dimensions_outer_circleL(2)] % center position on the screen baseRect_outer = [ObL.outer_circle.dimension]; % place in the first quarter ObL.outer_circle.dimension = CenterRectOnPoint(baseRect_outer, first_quarter, misure_schermo(4)/2); % same goes for the other circles ObL.inner_circle.color = inner_circle_color; ObL.inner_circle.dimension = [0 0 dimensions_inner_circleL(2) dimensions_inner_circleL(2)] baseRect_inner = [ObL.inner_circle.dimension]; % place in the first quarter ObL.inner_circle.dimension = CenterRectOnPoint(baseRect_inner, first_quarter, misure_schermo(4)/2); ObL.middle_circle.color = middle_circle_color; ObL.middle_circle.dimension = [0 0 dimensions_middle_circleL(2) dimensions_middle_circleL(2)] baseRect_middle = [ObL.middle_circle.dimension]; % place in the first quarter ObL.middle_circle.dimension = CenterRectOnPoint(baseRect_middle, first_quarter, misure_schermo(4)/2); %% SET ALL THE VISUALS on the RIGHT % proportion with respect to the entire screen set_proportion_of_diameter_outer_circleR = outer_dimension; prop_diameter_outer_circleR = [set_proportion_of_diameter_outer_circleR]; % transform proportions to actual pixels --> we get dimaeter of outer % circle in pixels dimensions_outer_circleR = MoBi_prop2dim(misure_schermo, 0, prop_diameter_outer_circleR); % same procedure for inner and middle circle calculated on the basis of the outer % circle prop_diameter_inner_circleR = inner_dimensionR*prop_diameter_outer_circleR; dimensions_inner_circleR = MoBi_prop2dim(misure_schermo, 0, prop_diameter_inner_circleR); prop_diameter_middle_circleR = middle_dimensionR*prop_diameter_outer_circleR; dimensions_middle_circleR = MoBi_prop2dim(misure_schermo, 0, prop_diameter_middle_circleR); %% generate a structure for the RIGHT circle with the features of the circle as fields % ...color ObR.outer_circle.color = outer_circle_color; % ...diameter ObR.outer_circle.dimension = [0 0 dimensions_outer_circleR(2) dimensions_outer_circleR(2)]; % center position on the screen; baseRect_outer = [ObR.outer_circle.dimension]; % place in the first quarter ObR.outer_circle.dimension = CenterRectOnPoint(baseRect_outer, last_quarter, misure_schermo(4)/2);% da che cosa dipendono questi numeri??? % same goes for the other circles ObR.inner_circle.color = inner_circle_color; ObR.inner_circle.dimension = [0 0 dimensions_inner_circleR(2) dimensions_inner_circleR(2)] baseRect_inner = [ObR.inner_circle.dimension]; % place in the last quarter ObR.inner_circle.dimension = CenterRectOnPoint(baseRect_inner, last_quarter, misure_schermo(4)/2); ObR.middle_circle.color = middle_circle_color; ObR.middle_circle.dimension = [0 0 dimensions_middle_circleR(2) dimensions_middle_circleR(2)] baseRect_middle = [ObR.middle_circle.dimension]; % place in the last quarter ObR.middle_circle.dimension = CenterRectOnPoint(baseRect_middle, last_quarter, misure_schermo(4)/2); %% we also have a black background. let's treat it as a structre as well. Bk.color = [0 0 0]; Bk.dimension = misure_schermo; %% resolution setting: % every time participant presses, read values change. here we set the boundary values to which a variable circle will change its diameter based on the pressure produced % create a vector from 0 to diameter of outer circle in steps of % length(x) diameter_values_nonscaled_tmp = linspace(0, dimensions_outer_circleL(2), length(x)); % in case participants press more than what they did in the max_force % evaluation, values bigger that outer_circle diameter are added, in order % not to get errors. % It should not happen though because it would mean the max_force % estimatimation was performed in a shitty way. diameter_values_nonscaled = [diameter_values_nonscaled_tmp ... diameter_values_nonscaled_tmp(end)+[1:100].*diff(diameter_values_nonscaled_tmp(1:2))]; %% INSTRUCTIONS FOR the researcher Screen('FillRect', window, Bk.color, Bk.dimension); Screen('TextSize', window, 25); hor_alignement = round(misure_schermo(3)*0.5,0); ver_alignement = round(misure_schermo(4)*0.25,0); TMS_cond = contraction_task{1,1}; DrawFormattedText(window,TMS_cond, hor_alignement,... ver_alignement, [1 1 1]); clear hor_alignement ver_alignement testo_sx = contraction_task{1,2}; hor_alignement = round(misure_schermo(3)*0.25,0); ver_alignement = round(misure_schermo(4)*0.75,0); DrawFormattedText(window,testo_sx, hor_alignement,... ver_alignement, [1 1 1]); clear hor_alignement ver_alignement testo_dx = contraction_task{1,3}; hor_alignement = round(misure_schermo(3)*0.75,0); ver_alignement = round(misure_schermo(4)*0.75,0); DrawFormattedText(window,testo_dx, hor_alignement,... ver_alignement, [1 1 1]); clear hor_alignement ver_alignement [VBL]=Screen(window, 'Flip', ifi, 1); % wait for keyboard press WaitSecs(2) %% while ~KbCheck end %% start noise [audiodata, infreq] = psychwavread('AirCool_Magstim_48000.wav'); noise_seconds = 60*5; noise_short = audiodata(1:infreq*noise_seconds)'; pasound2 = PsychPortAudio('Open', []); sound2 = [noise_short; noise_short]; PsychPortAudio('Volume', pasound2, volume); PsychPortAudio('FillBuffer', pasound2, sound2); noise_ts = PsychPortAudio('Start',pasound2, 1, 1); %% RUN TIME ACTUAL EXPERIMENT Screen('FillRect', window, [0 0 0], misure_schermo); [VBL]=Screen(window, 'Flip', ifi, 1); tic on_spot = 0; for tr = 1:num_trials i = 0; while 1 % read from serial port what arduino has written force_tmp = MoBi_scrittura(s); % split the 3 values that are read from the three pins in arduino force_tmp2 = (strsplit(force_tmp, '_')); % GET INFO ONLY FROM THE A0 PIN, which is the first read force_tmpL = str2double(force_tmp2{1}); force_tmpR = str2double(force_tmp2{2}); % force linearization. [linear_forceL idxL] = MoBi_linearize_force(force_tmpL, linearizeL, funzL); [linear_forceR idxR] = MoBi_linearize_force(force_tmpR, linearizeR, funzR); %% diameter_valuesL = diameter_values_nonscaled(idxL); diameter_valuesR = diameter_values_nonscaled(idxR); if on_spot == 0 % draw left side circles in background ObL.variable_circle.color = variable_circle_colorL; ObL.variable_circle.dimension = [0 0 diameter_valuesL diameter_valuesL]; baseRect_variable = [ObL.variable_circle.dimension]; ObL.variable_circle.dimension = CenterRectOnPoint(baseRect_variable, first_quarter, misure_schermo(4)/2); Screen('FrameOval', window, ObL.outer_circle.color, ObL.outer_circle.dimension); Screen('FillOval', window, ObL.middle_circle.color, ObL.middle_circle.dimension); Screen('FillOval', window, ObL.inner_circle.color, ObL.inner_circle.dimension); Screen('FrameOval', window, ObL.variable_circle.color, ObL.variable_circle.dimension, variable_circle_thickness); % draw right side circles in background ObR.variable_circle.color = variable_circle_colorR; ObR.variable_circle.dimension = [0 0 diameter_valuesR diameter_valuesR]; baseRect_variable = [ObR.variable_circle.dimension]; ObR.variable_circle.dimension = CenterRectOnPoint(baseRect_variable, last_quarter, misure_schermo(4)/2); Screen('FrameOval', window, ObR.outer_circle.color, ObR.outer_circle.dimension); Screen('FillOval', window, ObR.middle_circle.color, ObR.middle_circle.dimension); Screen('FillOval', window, ObR.inner_circle.color, ObR.inner_circle.dimension); Screen('FrameOval', window, ObR.variable_circle.color, ObR.variable_circle.dimension, variable_circle_thickness); Screen('TextSize', window, 80); DrawFormattedText(window, '+', 'center','center', [1 1 1]); else Screen('FillRect', window, [0 0 0], misure_schermo); Screen('TextSize', window, 80); DrawFormattedText(window, '+', 'center','center', [1 1 1]); end % flip [VBL] = Screen(window, 'Flip', VBL+ifi_as); sprintf( '%f_%f_%f____%f_%f_%f', inner_force_limit_propL*max_force_left, linear_forceL, outer_force_limit_propL*max_force_left,... inner_force_limit_propR*max_force_right, linear_forceR, outer_force_limit_propR*max_force_right) %% check force range for TMS if (linear_forceL >= inner_force_limit_propL*max_force_left) && (linear_forceL <= outer_force_limit_propL*max_force_left)... && (linear_forceR >= inner_force_limit_propR*max_force_right) && (linear_forceR <= outer_force_limit_propR*max_force_right) i= i+1; on_spot = 1; Screen('FillRect', window, [0 0 0], misure_schermo); Screen('TextSize', window, 80); DrawFormattedText(window, '+', 'center','center', [1 1 1]); else % ... if force is out of range i = 0; on_spot = 0; % change colors of the circle that is out if (linear_forceL <= inner_force_limit_propL*max_force_left) || (linear_forceL >= outer_force_limit_propL*max_force_left)... variable_circle_colorL = [1 0 0]; else variable_circle_colorL = [0 1 0]; end if (linear_forceR <= inner_force_limit_propR*max_force_right) || (linear_forceR >= outer_force_limit_propR*max_force_right) variable_circle_colorR = [1 0 0]; else variable_circle_colorR = [0 1 0]; end end % in case i is equal or greater than than the frames to be waited % for TMS to be delivered, then deliver TMS if i >= TMS_int_nf(tr) can_i_trigger = 1; % function implementing also trigger value MoBi_Trigger(ioObj,address,TMS_trigger, can_i_trigger); can_i_trigger = 0; TR.TMS_timing(tr) = VBL; TR.i(tr) = i; TR.ns(tr) = TMS_int_ns(tr); TR.nf(tr) = TMS_int_nf(tr); TR.tictoc(tr) = toc; disp(strcat('TMS', '_', num2str(tr))) WaitSecs(delay_after_TMS) % break the while loop and start another trial break end end end sca % forces = struct; % forces.max_force_left = max_force_left; % forces.max_force_right = max_force_right; % forces.sbj = sbj; % forces.order = ordine % forces.block = block; % forces.within_ordine = row_tabella; % forces.session = blocco; PsychPortAudio('Stop', pasound2,0); PsychPortAudio('Close'); clear audiodata sound2 noise_short pasound2 sound2 save(data_subject) end