0001 function sync_roi = bml_sync_neuroomega_event(cfg)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 scan_step = bml_getopt(cfg,'scan_step',0.1);
0026 scan = bml_getopt(cfg,'scan',100);
0027 timewarp = bml_getopt(cfg,'timewarp',false);
0028 master_events = bml_getopt(cfg,'master_events');
0029 roi = bml_getopt(cfg,'roi');
0030 diagnostic_plot = bml_getopt(cfg,'diagnostic_plot',false);
0031 timetol = bml_getopt(cfg,'timetol',1e-6);
0032 min_events = bml_getopt(cfg,'min_events',10);
0033 strict = bml_getopt(cfg,'strict',false);
0034
0035 assert(~isempty(roi),'roi required');
0036 assert(~isempty(master_events),'master_events required');
0037
0038 all_slave_dt = zeros(height(roi),1);
0039 all_warpfactor = ones(height(roi),1);
0040 all_meanerror = zeros(height(roi),1);
0041 for i=1:height(roi)
0042
0043
0044 i_slave_events = bml_read_event(roi(i,:));
0045 if isempty(i_slave_events) || length(i_slave_events) < min_events
0046 all_slave_dt(i) = nan;
0047 all_warpfactor(i) = nan;
0048 else
0049 cfg=[]; cfg.Fs = 1;
0050 cfg.starts = roi.starts(i);
0051 i_slave_events = bml_event2annot(cfg,i_slave_events);
0052 i_slave_events = bml_annot_table(i_slave_events);
0053
0054
0055 cfg=[];
0056 cfg.scan=scan;
0057 cfg.scan_step=scan_step;
0058 cfg.timewarp = timewarp;
0059 [slave_dt, min_cost, warpfactor]=bml_timealign_annot(cfg,master_events,i_slave_events);
0060 all_slave_dt(i) = slave_dt;
0061 all_warpfactor(i) = warpfactor;
0062
0063 if diagnostic_plot
0064 tbar = mean(i_slave_events.starts);
0065 i_slave_events_starts = (i_slave_events.starts - tbar) .* warpfactor + tbar + slave_dt;
0066 figure;
0067 plot(master_events.starts,ones(1,height(master_events)),'bo');
0068 hold on;
0069 plot(i_slave_events_starts,ones(1,length(i_slave_events_starts)),'r*');
0070 end
0071
0072 all_meanerror(i) = min_cost/height(i_slave_events);
0073 if all_meanerror(i) > timetol
0074 if strict
0075 error('could not time align within timetol. Mean error %f > %f. File %s',all_meanerror(i),timetol,roi.name{i});
0076 else
0077 warning('could not time align within timetol. Mean error %f > %f. File %s. Ignoring this file during consolidation.',all_meanerror(i),timetol,roi.name{i});
0078 all_slave_dt(i) = nan;
0079 all_warpfactor(i) = nan;
0080 end
0081 end
0082 end
0083 end
0084
0085 if ~timewarp
0086 all_slave_dt = repmat(nanmean(all_slave_dt),length(all_slave_dt),1);
0087 end
0088
0089
0090 roi.slave_dt = all_slave_dt;
0091 roi.warpfactor = all_warpfactor;
0092 roi.alignment_error = all_meanerror;
0093
0094 cfg=[];
0095 cfg.criterion = @(x) (abs((max(x.ends)-min(x.starts))-sum(x.duration))<10e-3);
0096 cont_roi = bml_annot_consolidate(cfg,roi);
0097
0098 consolidated_roi = table();
0099 for i=1:height(cont_roi)
0100 i_roi = roi(roi.id >= cont_roi.id_starts(i) & roi.id <= cont_roi.id_ends(i),:);
0101 i_roi.slave_dt(:) = nanmean(i_roi.slave_dt);
0102 i_roi.warpfactor(:) = nanmean(i_roi.warpfactor);
0103 consolidated_roi = [consolidated_roi; i_roi];
0104 end
0105 roi = consolidated_roi;
0106
0107 if any(ismissing(roi.slave_dt))
0108 warning('Using mean dt for some files');
0109 roi.slave_dt(ismissing(roi.slave_dt)) = nanmean(roi.slave_dt);
0110 end
0111 if any(ismissing(roi.warpfactor))
0112 warning('Using mean warpfactor for some files');
0113 roi.warpfactor(ismissing(roi.warpfactor)) = nanmean(roi.warpfactor);
0114 end
0115
0116 midpoint_a = (roi.ends + roi.ends) ./ 2;
0117 midpoint_t = (roi.t1 + roi.t2) ./ 2;
0118 roi.starts = (roi.starts - midpoint_a) .* roi.warpfactor + midpoint_a + roi.slave_dt;
0119 roi.ends = (roi.ends - midpoint_a) .* roi.warpfactor + midpoint_a + roi.slave_dt;
0120 roi.t1 = (roi.t1 - midpoint_t) .* roi.warpfactor + midpoint_t + roi.slave_dt;
0121 roi.t2 = (roi.t2 - midpoint_t) .* roi.warpfactor + midpoint_t + roi.slave_dt;
0122
0123 roi.chunk_id = (1:height(roi))';
0124 roi.sync_channel = repmat({'digital'},height(roi),1);
0125 roi.sync_type = repmat({'slave'},height(roi),1);
0126
0127 sync_roi = bml_roi_table(roi);
0128
0129 sync_roi(:,{'id','starts','ends','duration','name','warpfactor'})
0130