Home > utils > extract_controller.m

extract_controller

PURPOSE ^

extract_controller.m

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

 extract_controller.m

 Extracts controller data

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 % extract_controller.m
0002 %
0003 % Extracts controller data
0004 
0005 LOAD_DATA_FROM_MID = 0;
0006 LOAD_DATA_FROM_TXT = 0;
0007 LOAD_DATA_FROM_TR =0;
0008 
0009 DO_PLOTS = 1;
0010 PLOT_INDIV = 0;
0011 PLOT_AVG = 1;
0012 
0013 INITIAL_AMP_THRESHOLD = 5;
0014 TIME_THRESHOLD = 2;
0015 
0016 MIN_SEG_DUR = 0.1;  % minimum duration of 100 ms
0017 MAX_SEG_DUR = 2;
0018 
0019 MAX_GLUE_SEP = 0.5;  % max separation in seconds between segments to be glued
0020 
0021 spline_tscale = 0:0.01:MAX_SEG_DUR;
0022 
0023 % Columns in the pmat matrix
0024 miditoolbox_params;
0025 
0026 datapath = '/afs/cmb/usr/petr/projects/contpopout/data';
0027 fstub = 'timbre_only_CC';
0028 use_track = 2;
0029 
0030 fname = fullfile(datapath,sprintf('%s.mid', fstub));
0031 
0032 if LOAD_DATA_FROM_MID
0033   tr = javareadmidi(fname);
0034 end
0035 
0036 if LOAD_DATA_FROM_TXT
0037     tr = readmidi2tr(fname);
0038     outfname = fullfile(datapath, sprintf('%s_tr.mat',fstub));
0039     fprintf('Saving converted track info to %s\n', outfname);
0040     save(outfname,'tr')
0041 end
0042 
0043 if LOAD_DATA_FROM_TR
0044   infname = fullfile(datapath, sprintf('%s_tr.mat', fstub));
0045   fprintf('Loading data from %s\n', infname)
0046   load(infname)
0047 end
0048 
0049 % Parse individual events based on threshold
0050 
0051 % Find all values above some threshold and find start and stop boundaries of
0052 % each chunk
0053 
0054 time_vals = tr(use_track).pmat(:,CONTROLLER_SEC_COL);
0055 slider_vals = tr(use_track).pmat(:,CONTROLLER_VAL_COL);
0056 
0057 % Get potential segmentation markers based on time values
0058 time_diff_vect = diff([0; time_vals]);
0059 time_diff_mask = time_diff_vect > TIME_THRESHOLD;
0060 time_seg_onset_idxs = find(time_diff_mask);
0061 num_time_segs = length(time_seg_onset_idxs);
0062 
0063 % Get potential segmentation markers based on controller values
0064 diff_vect = diff([0; slider_vals>INITIAL_AMP_THRESHOLD; 0]);
0065 
0066 % Check to see if the number of positive transitions matches the number of
0067 % negative transitions
0068 if sum(diff_vect)
0069   fprintf('Mismatched numbers of positive and negative transitions\n')
0070   seg_start_stop_idx = [];
0071 else
0072   seg_start_stop_idx = [find(diff_vect>0) find(diff_vect<0)-1];
0073 end
0074 
0075 num_val_segs = size(seg_start_stop_idx,1);
0076 
0077 % Display some information about segmentation markers that were identified
0078 fprintf('Number of segments based on temporal threshold of %1.1f s: %d\n', TIME_THRESHOLD, num_time_segs);
0079 fprintf('Number of segments based on value threshold of %d: %d\n', INITIAL_AMP_THRESHOLD, num_val_segs);
0080 
0081 % Handle each individual segment that is above threshold
0082 segment = struct('idxs',[],'tscale',[],'vals',[]);
0083 for iseg = 1:num_val_segs
0084   start_idx = seg_start_stop_idx(iseg,1);
0085   stop_idx = seg_start_stop_idx(iseg,2);
0086   segments(iseg).startstop = [start_idx stop_idx];
0087   segments(iseg).tscale = time_vals(start_idx:stop_idx);
0088   segments(iseg).vals = slider_vals(start_idx:stop_idx);
0089 
0090   % make sure tscale values are unique
0091   bad_idxs = find(~diff(time_vals(start_idx:stop_idx)))+1;
0092   segments(iseg).tscale(bad_idxs) = [];
0093   segments(iseg).vals(bad_idxs) = [];
0094   
0095   segments(iseg).dur = max(segments(iseg).tscale)-min(segments(iseg).tscale);
0096 
0097   % some metrics for error-checking purposes
0098   segments(iseg).initial_is_max = segments(iseg).vals(1) == max(segments(iseg).vals);
0099   segments(iseg).final_is_max = segments(iseg).vals(end) == ...
0100       max(segments(iseg).vals);
0101   segments(iseg).nsamps = length(segments(iseg).vals);
0102   
0103 end % for iseg=
0104 
0105 % Flag segments as potentially bad based on various criteria
0106 bad_dur_mask = [segments.dur] < MIN_SEG_DUR;
0107 fprintf('\t%d segments shorter than minimum criterion of %1.2f s\n', sum(bad_dur_mask), MIN_SEG_DUR);
0108 
0109 % Delete segments that are flagged as bad
0110 segments(bad_dur_mask) = [];
0111 
0112 % Identify that pairs of segments that should maybe be part of the same
0113 % segment, i.e. they were severed based on sudden erroneous drop out that
0114 % caused a boundary.  The following conditions are symptomatic of such cases:
0115 %
0116 % Bounds of segment are above some criterion threshold
0117 %
0118 % Segment severed during rise:
0119 %   max(seg1) is final sample
0120 %
0121 % Segment severed during fall
0122 %   max(seg2) is initial sample
0123 
0124 max_final_mask = [segments.final_is_max];
0125 max_initial_mask = [segments.initial_is_max];
0126 
0127 glue_segs = find(all([max_final_mask(1:end-1); max_initial_mask(2:end)]));
0128 
0129 fprintf('Found %d segments to glue together\n', length(glue_segs));
0130 for iseg = 1:length(glue_segs)
0131   gs = glue_segs(iseg);
0132   
0133   % Make sure that segments to be glued are within a criterion time window of
0134   % each other
0135   seg_sep = segments(gs+1).tscale(1)-segments(gs).tscale(end);
0136   if seg_sep <= MAX_GLUE_SEP;
0137     fprintf('\tGluing segment %d and segment %d\n', [0 1]+gs);
0138     segments(gs).startstop(2) = ...
0139     segments(gs+1).startstop(2);
0140     segments(gs).tscale = [segments(gs).tscale; ...
0141       segments(gs+1).tscale];
0142     segments(gs).vals = [segments(gs).vals; ...
0143       segments(gs+1).vals];
0144     segments(gs).dur = diff(segments(gs).tscale([1 end]));
0145     segments(gs).nsamps = length(segments(gs).vals);
0146     segments(gs).final_is_max = 0;
0147   end
0148 end % for iseg -- gluing
0149 
0150 segments(glue_segs+1) = [];
0151 
0152 % Toss segments that are too long
0153 bad_dur_mask = [segments.dur] > MAX_SEG_DUR;
0154 fprintf('\t%d segments longer than maximum criterion of %1.2f s\n', sum(bad_dur_mask), MAX_SEG_DUR);
0155 
0156 % Delete segments that are flagged as bad
0157 segments(bad_dur_mask) = [];
0158 
0159 %
0160 %  Interpolate the segments onto a common mesh so that they can be averaged
0161 %
0162 
0163 nseg = length(segments);
0164 for iseg = 1:nseg
0165   % Set final value in segment to zero so that interpolation works
0166   segments(iseg).vals(end+1) = segments(iseg).vals(end);
0167   segments(iseg).tscale(end+1) = segments(iseg).tscale(end)+0.01;
0168 
0169   curr_tscale = segments(iseg).tscale-segments(iseg).tscale(1);
0170   
0171   % Do some spline interpolation and plot the waveform
0172   %segments(iseg).cs = spline(curr_tscale,[0; segments(iseg).vals; 0]);
0173   segments(iseg).cs = pchip(curr_tscale,[segments(iseg).vals]);
0174   
0175   segments(iseg).resamp = ppval(segments(iseg).cs,spline_tscale);
0176 end
0177 
0178 
0179 % Check for multiple peaks in a chunk. Multiple peaks might be an indication of
0180 % multiple responses within a chunk, and/or the slider not being returned
0181 % to zero.
0182 
0183 if DO_PLOTS
0184   if PLOT_INDIV
0185     plot(curr_tscale,segments(iseg).vals,spline_tscale,segments(iseg).resamp,'r')
0186     title(sprintf('Segment %d/%d', iseg, nseg))
0187     pause
0188   end
0189   if PLOT_AVG
0190     figure(1),clf
0191     subplot(2,1,1)
0192     resp_mat = cat(1,segments.resamp);
0193     nresp = size(resp_mat,1);
0194     imagesc(spline_tscale,1:nresp,resp_mat), axis xy
0195     set(gca,'xlim',[0 MAX_SEG_DUR])
0196     
0197     subplot(2,1,2)
0198     errorbar(spline_tscale,mean(resp_mat),std(resp_mat)/sqrt(nresp))
0199     set(gca,'xlim',[0 MAX_SEG_DUR])
0200     title(sprintf('Mean response profile: %d responses',nresp))
0201   end
0202 end

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003