137137
138138 if remaining_valid_trials < merge_threshold && state .block_count > 0
139139 last_block_indices = state .blockStatsHistory(end ).indices;
140- combined_indices = [last_block_indices , new_valid_indices ' ];
140+ combined_indices = [last_block_indices( : ) ' , new_valid_indices( : ) ' ];
141141
142142 dataBuffer.stim = data .stim_history(combined_indices );
143143 dataBuffer.hit = data .hit_history(combined_indices );
260260 stim_hist_data{i }.correct = histcounts(stim_fit(hit_fit == 1 ), bin_edges );
261261 stim_hist_data{i }.incorrect = histcounts(stim_fit(hit_fit == 0 ), bin_edges );
262262
263+ % Since plotting Histcounts instead of mean its not useful
264+
263265 relevant_blocks = [];
264266 for j = 1 : numel(state .blockStatsHistory )
265267 block_indices = state .blockStatsHistory(j ).indices;
266268 if min(block_indices ) >= start_idx && max(block_indices ) <= end_idx
267269 relevant_blocks = [relevant_blocks , state .blockStatsHistory(j )];
268270 end
269271 end
270-
272+
271273 if ~isempty(relevant_blocks )
272274 hit_rate_std(i , 1 ) = std(arrayfun(@(blk ) blk .hitRates .overall , relevant_blocks ), ' omitnan' );
273275 hit_rate_std(i , 2 ) = std(arrayfun(@(blk ) blk .hitRates .left , relevant_blocks ), ' omitnan' );
274276 hit_rate_std(i , 3 ) = std(arrayfun(@(blk ) blk .hitRates .right , relevant_blocks ), ' omitnan' );
275277 correct_cells = arrayfun(@(s ) s .stimCounts .correct(: )' , relevant_blocks , ' UniformOutput' , false );
276- counts_matrix_corr = cell2mat (correct_cells );
278+ counts_matrix_corr = vertcat (correct_cells{ : } );
277279 incorrect_cells = arrayfun(@(s ) s .stimCounts .incorrect(: )' , relevant_blocks , ' UniformOutput' , false );
278- counts_matrix_incorr = cell2mat (incorrect_cells );
280+ counts_matrix_incorr = vertcat (incorrect_cells{ : } );
279281 stim_hist_data{i }.mean_corr = mean(counts_matrix_corr , 1 );
280282 stim_hist_data{i }.std_corr = std(counts_matrix_corr , 0 , 1 );
281283 stim_hist_data{i }.mean_incorr = mean(counts_matrix_incorr , 1 );
282284 stim_hist_data{i }.std_incorr = std(counts_matrix_incorr , 0 , 1 );
283285 else
284286 hit_rate_std(i , : ) = 0 ;
285287 end
288+
286289 end
287290
288291 if flags .psych , plotContextPsychometric(handles .axes_h .custom_psych , psych_data , config , context_colors ,contexts_names ); end
401404 function state = reAnalyzeLastChunk(state , data , handles , config , dataBuffer , flags )
402405 [newBlockStat , newRow ] = processBlock(data , config , dataBuffer );
403406 state .blockStatsHistory(end ) = newBlockStat ;
404- replaceLastTableRow(handles , newRow );
407+ last_editable_row = find(state .table_row_editable == 1 ,1 ,' last' );
408+ replaceLastTableRow(handles , newRow ,last_editable_row );
405409
406410 state.last_analyzed_valid_trial = sum(~isnan(data .hit_history ));
407411
@@ -461,18 +465,18 @@ function updateTable(handles, newRow)
461465 set(handles .ui_table , ' Data' , [currentData ; newRow ]);
462466 end
463467
464- function replaceLastTableRow(handles , newRow )
468+ function replaceLastTableRow(handles , newRow , row_num )
465469 currentData = get(handles .ui_table , ' Data' );
466470 if ~isempty(currentData )
467471 newRow{1 } = true ; % Select the new row
468- currentData(end ,: ) = newRow ;
472+ currentData(row_num ,: ) = newRow ;
469473 set(handles .ui_table , ' Data' , currentData );
470474 end
471475 end
472476
473477 function updateLivePlots(state , data , handles , config , flags )
474478 if flags .psych , updatePsychometricPlot(handles .axes_h .live_psych , handles .ui_table , config ); end
475- if flags .hit , updateHitRatePlot(handles .axes_h .live_hitrate ,state . context_blocks , handles .ui_table ); end
479+ if flags .hit , updateHitRatePlot(handles .axes_h .live_hitrate , state , handles .ui_table ); end
476480 if flags .stim , updateStimulusHistogram(handles .axes_h .live_stim , state , data , config ,handles .ui_table ); end
477481 end
478482
@@ -519,15 +523,17 @@ function updatePsychometricPlot(ax, ui_table_handle, config)
519523 ylabel(ax , ' P(Choice)' ); title(ax , ' Live Psychometric Curves' );
520524 end
521525
522- function updateHitRatePlot(ax , context_blocks , ui_table_handle )
526+ function updateHitRatePlot(ax , state , ui_table_handle )
523527 allData = get(ui_table_handle , ' Data' );
524528 if isempty(allData )
525529 cla(ax , ' reset' );
526530 return ;
527531 end
528532
529- logical_mask = allData .Select == 1 ;
530- selectedData = allData(logical_mask , : );
533+ % Changed from only the user selected rows to show all rows as it is a line plot
534+ selectedData = allData(logical(state .table_row_editable ),: );
535+ % logical_mask = allData.Select == 1;
536+ % selectedData = allData(logical_mask, :);
531537
532538 cla(ax , ' reset' );
533539 if isempty(selectedData )
@@ -546,9 +552,9 @@ function updateHitRatePlot(ax, context_blocks, ui_table_handle)
546552 plot(ax , x_axis , hr_left , ' --ob' , ' LineWidth' , 1.5 , ' DisplayName' , ' Left' );
547553 plot(ax , x_axis , hr_right , ' --or' , ' LineWidth' , 1.5 , ' DisplayName' , ' Right' );
548554 % plotting context change
549- if length(context_blocks ) > 1
550- for k = 2 : length(context_blocks )
551- xline(ax , context_blocks(k ), ' --k' , ' LineWidth' , 1.5 , ' HandleVisibility' , ' off' );
555+ if length(state . context_blocks ) > 1
556+ for k = 2 : length(state . context_blocks )
557+ xline(ax , state . context_blocks(k ), ' --k' , ' LineWidth' , 1.5 , ' HandleVisibility' , ' off' );
552558 end
553559 end
554560 hold(ax , ' off' ); legend(ax , ' show' , ' Location' , ' southeast' );
@@ -567,43 +573,53 @@ function updateStimulusHistogram(ax, state, data, config, ui_table_handle)
567573 end
568574
569575 logical_mask = allData .Select == 1 ;
570- selected_indices = find(logical_mask ); % Get row numbers of selected blocks
571-
572-
576+ selected_table_indices = find(logical_mask ); % Row numbers from the full table (e.g., [12, 25, 48])
577+
573578 cla(ax , ' reset' );
574- if isempty(selected_indices )
579+ if isempty(selected_table_indices )
575580 title(ax , ' Live Choice Distribution (Nothing Selected)' );
576581 return ;
577582 end
583+
584+ editable_table_indices = find(state .table_row_editable ); % Get the list of row numbers that are actually editable
585+ % This maps the full-table indices to the smaller blockStatsHistory indices.
586+ [~ , block_indices_to_plot ] = ismember(selected_table_indices , editable_table_indices );
587+ % Clean up the indices (removes any zeros if a non-editable row was somehow selected)
588+ block_indices_to_plot = block_indices_to_plot(block_indices_to_plot > 0 );
589+
590+ if isempty(block_indices_to_plot )
591+ title(ax , ' Live Choice Distribution (Nothing Selected)' );
592+ return ;
593+ end
594+ n_selected_blocks = numel(block_indices_to_plot );
578595
579- n_selected_blocks = numel( selected_indices );
596+ % The rest of your plotting setup is correct
580597 red_map = interp1([0 1 ], [1 0.7 0.7 ; 0.9 0.2 0.1 ], linspace(0 , 1 , n_selected_blocks ));
581598 green_map = interp1([0 1 ], [0.7 1 0.7 ; 0 0.65 0 ], linspace(0 , 1 , n_selected_blocks ));
582-
599+
583600 left_edges = linspace(min(config .stimuli_range ), config .true_mu , 6 );
584601 right_edges = linspace(config .true_mu , max(config .stimuli_range ), 6 );
585602 bin_edges = unique([left_edges , right_edges ]);
586603 bin_centers = (bin_edges(1 : end - 1 ) + bin_edges(2 : end )) / 2 ;
587-
604+
588605 yyaxis(ax , ' left' );
589606 hold(ax , ' on' );
590607 yyaxis(ax , ' right' );
591608 hold(ax , ' on' );
592-
593609 max_count = 0 ;
594610
595611 for i = 1 : n_selected_blocks
596- block_idx = selected_indices (i ); % Use the index of the selected row
612+ block_idx = block_indices_to_plot (i );
597613 block_stat = state .blockStatsHistory(block_idx );
598614
599- multiplier = 1 ;
615+ multiplier = 1 ;
600616 if i == n_selected_blocks , multiplier = 2 ; end
601-
617+
602618 yyaxis(ax , ' left' );
603619 plot(ax , bin_centers , block_stat .stimCounts .incorrect , ' -' , ' Color' , red_map(i ,: ), ' LineWidth' , multiplier * 1.5 );
604620 plot(ax , bin_centers , block_stat .stimCounts .correct , ' -' , ' Color' , green_map(i ,: ), ' LineWidth' , multiplier * 1.5 );
605621 max_count = max([max_count , block_stat .stimCounts .correct , block_stat .stimCounts .incorrect ]);
606-
622+
607623 yyaxis(ax , ' right' );
608624 block_indices_raw = block_stat .indices ;
609625 valid_mask = ~isnan(data .hit_history(block_indices_raw ));
@@ -712,37 +728,37 @@ function plotCustomStimulusHistogram(ax, stim_fit, hit_fit, custom_range, blockS
712728 counts_custom.correct = histcounts(stim_fit(hit_fit == 1 ), bin_edges );
713729 counts_custom.incorrect = histcounts(stim_fit(hit_fit == 0 ), bin_edges );
714730
715- relevant_blocks = [];
716- for i = 1 : numel( blockStats )
717- block_indices = blockStats( i ).indices ;
718- if min( block_indices ) >= custom_range( 1 ) && max( block_indices ) <= custom_range( 2 )
719- relevant_blocks = [ relevant_blocks , blockStats(i )] ;
720- end
721- end
722-
723- if ~isempty( relevant_blocks )
724- correct_cells = arrayfun(@( blk ) blk . stimCounts . correct , relevant_blocks , ' UniformOutput ' , false );
725- incorrect_cells = arrayfun(@( blk ) blk . stimCounts . incorrect , relevant_blocks , ' UniformOutput ' , false );
726-
727- counts_matrix_corr = cell2mat( correct_cells );
728- counts_matrix_incorr = cell2mat( incorrect_cells );
729-
730- mean_corr = mean( counts_matrix_corr , 1 );
731- std_corr = std( counts_matrix_corr , 0 , 1 );
732- mean_incorr = mean( counts_matrix_incorr , 1 );
733- std_incorr = std(counts_matrix_incorr , 0 , 1 );
734-
735- if sum(std_corr ) > eps
736- fill(ax , [bin_centers , fliplr(bin_centers )], [mean_corr - std_corr , fliplr(mean_corr + std_corr )], ...
737- [0 0.65 0 ], ' FaceAlpha' , 0.2 , ' EdgeColor' , ' none' , ' DisplayName' , ' Correct (Block STD)' );
738- end
739-
740- % --- Plot the fill area for INCORRECT trials, only if there is variance ---
741- if sum(std_incorr ) > eps
742- fill(ax , [bin_centers , fliplr(bin_centers )], [mean_incorr - std_incorr , fliplr(mean_incorr + std_incorr )], ...
743- [0.9 0.2 0.1 ], ' FaceAlpha' , 0.2 , ' EdgeColor' , ' none' , ' DisplayName' , ' Incorrect (Block STD)' );
744- end
745- end
731+ % Since plotting histcounts instead of mean so not useful
732+
733+ % relevant_blocks = [] ;
734+ % for i = 1:numel(blockStats )
735+ % block_indices = blockStats(i).indices ;
736+ % if min(block_indices) >= custom_range(1) && max(block_indices) <= custom_range(2)
737+ % relevant_blocks = [relevant_blocks, blockStats(i)];
738+ % end
739+ % end
740+ %
741+ % if ~isempty( relevant_blocks)
742+ % correct_cells = arrayfun(@(blk) blk.stimCounts.correct, relevant_blocks,'UniformOutput',false);
743+ % incorrect_cells = arrayfun(@(blk) blk.stimCounts.incorrect, relevant_blocks,'UniformOutput',false );
744+ %
745+ % counts_matrix_corr = vertcat(correct_cells{:});
746+ % counts_matrix_incorr = vertcat(incorrect_cells{:} );
747+ %
748+ % std_corr = std(counts_matrix_corr, 0 , 1);
749+ % std_incorr = std(counts_matrix_incorr, 0, 1);
750+ %
751+ % if sum(std_corr) > eps
752+ % fill(ax, [bin_centers, fliplr(bin_centers)], [counts_custom.correct - std_corr, fliplr(counts_custom.correct + std_corr)], ...
753+ % [0 0.65 0], 'FaceAlpha', 0.2, 'EdgeColor', 'none', 'DisplayName', 'Correct (Block STD)');
754+ % end
755+ %
756+ % % --- Plot the fill area for INCORRECT trials, only if there is variance ---
757+ % if sum(std_incorr) > eps
758+ % fill(ax, [bin_centers, fliplr(bin_centers)], [counts_custom.incorrect - std_incorr, fliplr(counts_custom.incorrect + std_incorr)], ...
759+ % [0.9 0.2 0.1], 'FaceAlpha', 0.2, 'EdgeColor', 'none', 'DisplayName', 'Incorrect (Block STD)');
760+ % end
761+ % end
746762
747763 plot(ax , bin_centers , counts_custom .correct , ' -o' , ' Color' , [0 0.65 0 ], ' LineWidth' , 2 , ' DisplayName' , ' Correct (Custom)' );
748764 plot(ax , bin_centers , counts_custom .incorrect , ' -o' , ' Color' , [0.9 0.2 0.1 ], ' LineWidth' , 2 , ' DisplayName' , ' Incorrect (Custom)' );
@@ -840,16 +856,16 @@ function plotContextStimulusHistogram(ax, stim_hist_data, config, colors,context
840856 for i = 1 : numel(stim_hist_data )
841857 if isempty(stim_hist_data{i }), continue ; end
842858
843- if isfield(stim_hist_data{i }, ' mean_corr' )
844- if sum(stim_hist_data{i }.std_corr) > eps
845- fill(ax , [bin_centers , fliplr(bin_centers )], [stim_hist_data{i }.mean_corr - stim_hist_data{i }.std_corr, fliplr(stim_hist_data{i }.mean_corr + stim_hist_data{i }.std_corr)], ...
846- colors(i ,: ), ' FaceAlpha' , 0.15 , ' EdgeColor' , ' none' );
847- end
848- if sum(stim_hist_data{i }.std_incorr) > eps
849- fill(ax , [bin_centers , fliplr(bin_centers )], [stim_hist_data{i }.mean_incorr - stim_hist_data{i }.std_incorr, fliplr(stim_hist_data{i }.mean_incorr + stim_hist_data{i }.std_incorr)], ...
850- colors(i ,: ), ' FaceAlpha' , 0.15 , ' EdgeColor' , ' none' );
851- end
852- end
859+ % if isfield(stim_hist_data{i}, 'mean_corr')
860+ % if sum(stim_hist_data{i}.std_corr) > eps
861+ % fill(ax, [bin_centers, fliplr(bin_centers)], [stim_hist_data{i}.correct - stim_hist_data{i}.std_corr, fliplr(stim_hist_data{i}.correct + stim_hist_data{i}.std_corr)], ...
862+ % colors(i,:), 'FaceAlpha', 0.15, 'EdgeColor', 'none');
863+ % end
864+ % if sum(stim_hist_data{i}.std_incorr) > eps
865+ % fill(ax, [bin_centers, fliplr(bin_centers)], [stim_hist_data{i}.incorrect - stim_hist_data{i}.std_incorr, fliplr(stim_hist_data{i}.incorrect + stim_hist_data{i}.std_incorr)], ...
866+ % colors(i,:), 'FaceAlpha', 0.15, 'EdgeColor', 'none');
867+ % end
868+ % end
853869
854870 plot(ax , bin_centers , stim_hist_data{i }.correct, ' -o' , ' Color' , colors(i ,: ), ' LineWidth' , 2 , ' DisplayName' , sprintf(' Correct C%d ' , i ));
855871 plot(ax , bin_centers , stim_hist_data{i }.incorrect, ' :x' , ' Color' , colors(i ,: ), ' LineWidth' , 1.5 , ' DisplayName' , sprintf(' Incorrect C%d ' , i ));
0 commit comments