From db58baff5a8fc5bda546a7687f0dcfcb73c7f6cd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:10:03 +0000 Subject: [PATCH 1/4] Fix time calculation in axon_abf reader to handle gaps Updated `ndr.reader.axon_abf.readchannels_epochsamples` to use `samples2times` for converting sample indices to time, ensuring correct handling of recordings with gaps (e.g., sweeps). Added special handling for the 'time' channel to avoid infinite recursion. --- +ndr/+reader/axon_abf.m | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/+ndr/+reader/axon_abf.m b/+ndr/+reader/axon_abf.m index 46de852..cc884a6 100755 --- a/+ndr/+reader/axon_abf.m +++ b/+ndr/+reader/axon_abf.m @@ -161,18 +161,21 @@ s1_ = 1; end; - sr = axon_abf_obj.get_samplerate_from_header(header, channel); - sr_unique = unique(sr); % get all sample rates - if numel(sr_unique)~=1, - error(['Do not know how to handle different sampling rates across channels.']); + if strcmpi(channeltype{1},'time'), + % we want to avoid infinite recursion + t0t1 = axon_abf_obj.get_t0_t1_from_header(header); + T = t0t1{1}; + else, + T = axon_abf_obj.samples2times(channeltype{1}, channel, epochstreams, epoch_select, [s0_ s1_]); end; - t0t1 = axon_abf_obj.get_t0_t1_from_header(header); - T = ndr.time.fun.samples2times([s0_ s1_], t0t1{1}, sr_unique); - % in abfread, the reader reads up to s1 -1 instead of s1 data = ndr.format.axon.read_abf(filename,header,channeltype{1},channel,T(1),T(2)); + if strcmpi(channeltype{1},'time'), + data = data(s0_:s1_); + end; + if numel(channel) == 1 data = data(:); end From a9c29b96d38130d47e67c0b1331d9c09399c9bb6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:12:24 +0000 Subject: [PATCH 2/4] Update GitHub badges --- .github/badges/code_issues.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/badges/code_issues.svg b/.github/badges/code_issues.svg index 40a2245..1bd6d59 100644 --- a/.github/badges/code_issues.svg +++ b/.github/badges/code_issues.svg @@ -1 +1 @@ -code issuescode issues12751275 \ No newline at end of file +code issuescode issues12761276 \ No newline at end of file From d199ac127ae2106d1b149a40e0fe4bfcd4701205 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:24:54 +0000 Subject: [PATCH 3/4] Fix time calculation in axon_abf reader to handle gaps and clean up syntax Updated `ndr.reader.axon_abf.readchannels_epochsamples` to use `samples2times` for converting sample indices to time, ensuring correct handling of recordings with gaps (e.g., sweeps). Added special handling for the 'time' channel to avoid infinite recursion. Additionally, removed unnecessary commas and semicolons throughout `ndr/reader/axon_abf.m` to reduce code warnings and improve readability. --- +ndr/+reader/axon_abf.m | 58 +++++++++++++++++----------------- .github/badges/code_issues.svg | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/+ndr/+reader/axon_abf.m b/+ndr/+reader/axon_abf.m index cc884a6..b0433f0 100755 --- a/+ndr/+reader/axon_abf.m +++ b/+ndr/+reader/axon_abf.m @@ -79,10 +79,10 @@ channels(1) = struct('name','t1','type','time','time_channel',1); - for i=1:numel(header.recChNames), + for i=1:numel(header.recChNames) channels(end+1) = struct('name',['ai' int2str(i)],... 'type','analog_in', 'time_channel', 1); - end; + end end % ndr.reader.axon_abf.getchannelsepoch function [datatype,p,datasize] = underlying_datatype(axon_abf_obj, epochstreams, epoch_select, channeltype, channel) @@ -107,25 +107,25 @@ header = ndr.format.axon.read_abf_header(filename); switch(channeltype) - case {'analog_in','analog_out','auxiliary_in'}, + case {'analog_in','analog_out','auxiliary_in'} % For the abstract class, keep the data in doubles. This will always work but may not % allow for optimal compression if not overridden datasize = ndr.fun.bitDepth(header.lADCResolution); datatype = ndr.fun.getDataTypeString(true,true,datasize); p = [0 header.fADCRange/header.lADCResolution]; - case {'time'}, + case {'time'} datatype = 'float64'; datasize = 64; p = [0 1]; - case {'digital_in','digital_out'}, + case {'digital_in','digital_out'} datatype = 'char'; datasize = 8; p = [0 1]; - case {'eventmarktext','event','marker','text'}, + case {'eventmarktext','event','marker','text'} datatype = 'float64'; datasize = 64; p = [0 1]; - otherwise, + otherwise error(['Unknown channel type ' channeltype '.']); end end @@ -148,33 +148,33 @@ [filename] = axon_abf_obj.filenamefromepochfiles(epochstreams); header = ndr.format.axon.read_abf_header(filename); - if ~iscell(channeltype), + if ~iscell(channeltype) channeltype = repmat({channeltype},numel(channel),1); - end; + end maxSamples = header.lActualAcqLength / header.nADCNumChannels; s0_ = max(1, s0); - if isinf(s0_), % could be positive inf + if isinf(s0_) % could be positive inf s0_ = maxSamples; - end; + end s1_ = min(maxSamples, s1); - if isinf(s1_), % could be negative infinity + if isinf(s1_) % could be negative infinity s1_ = 1; - end; + end - if strcmpi(channeltype{1},'time'), + if strcmpi(channeltype{1},'time') % we want to avoid infinite recursion t0t1 = axon_abf_obj.get_t0_t1_from_header(header); T = t0t1{1}; - else, + else T = axon_abf_obj.samples2times(channeltype{1}, channel, epochstreams, epoch_select, [s0_ s1_]); - end; + end % in abfread, the reader reads up to s1 -1 instead of s1 data = ndr.format.axon.read_abf(filename,header,channeltype{1},channel,T(1),T(2)); - if strcmpi(channeltype{1},'time'), + if strcmpi(channeltype{1},'time') data = data(s0_:s1_); - end; + end if numel(channel) == 1 data = data(:); @@ -194,9 +194,9 @@ % If CHANNELTYPE is a single string, then it is assumed that that % CHANNELTYPE applies to every entry of CHANNEL. % - if epoch_select~=1, + if epoch_select~=1 error(['ABF files have 1 epoch per file.']); - end; + end filename = axon_abf_obj.filenamefromepochfiles(epochstreams); @@ -216,12 +216,12 @@ [tf, matchstring, substring] = vlt.string.strcmp_substitution(s1,filename_array,'UseSubstituteString',0); index = find(tf); - if numel(index)==0, + if numel(index)==0 error(['Need at least 1 .abf file per epoch.']); - else, + else filename = filename_array{index(1)}; end - end; % ndr.reader.axon_abf.filenamefromepochfiles + end % ndr.reader.axon_abf.filenamefromepochfiles function channelstruct = daqchannels2internalchannels(ndr_reader_axon_abf_obj, channelprefix, channelnumber, epochstreams, epoch_select) % DAQCHANNELS2INTERNALCHANNELS - convert a set of DAQ channel prefixes and channel numbers to an internal structure to pass to internal reading functions @@ -262,7 +262,7 @@ channelstruct = vlt.data.emptystruct('internal_type','internal_number',... 'internal_channelname','ndr_type','samplerate'); - for i=1:numel(channels), + for i=1:numel(channels) newentry.internal_type = channels(i).type; [CHANNELNAMEPREFIX, numericchannel] = ndr.string.channelstring2channels(channels(i).name); newentry.internal_number = numericchannel; @@ -270,11 +270,11 @@ newentry.ndr_type = ndr.reader.base.mfdaq_type(newentry.internal_type); newentry.samplerate = ndr_reader_axon_abf_obj.samplerate(epochstreams,epoch_select,... CHANNELNAMEPREFIX, numericchannel); - if any( (newentry.internal_number(:) == channelnumber) & strcmp(channelprefix,CHANNELNAMEPREFIX) ), + if any( (newentry.internal_number(:) == channelnumber) & strcmp(channelprefix,CHANNELNAMEPREFIX) ) channelstruct(end+1) = newentry; - end; - end; - end; % daqchannels2internalchannels + end + end + end % daqchannels2internalchannels function t = samples2times(axon_abf_obj, channeltype, channel, epochstreams, epoch_select, s) % SAMPLES2TIMES - convert sample numbers to time @@ -319,7 +319,7 @@ if isfield(header,'uFileStartDate') dt = ndr.format.axon.abfTimeToDatetime(header.uFileStartDate,header.uFileStartTimeMS); t0t1{2} = [datenum(dt) datenum(dt+seconds(t1))]; - end; + end end function sr = get_samplerate_from_header(header, channel) diff --git a/.github/badges/code_issues.svg b/.github/badges/code_issues.svg index 1bd6d59..40a2245 100644 --- a/.github/badges/code_issues.svg +++ b/.github/badges/code_issues.svg @@ -1 +1 @@ -code issuescode issues12761276 \ No newline at end of file +code issuescode issues12751275 \ No newline at end of file From dacd269d8555171aeb6953239b2bb9d8d0bb5465 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:27:10 +0000 Subject: [PATCH 4/4] Update GitHub badges --- .github/badges/code_issues.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/badges/code_issues.svg b/.github/badges/code_issues.svg index 40a2245..3e3bca8 100644 --- a/.github/badges/code_issues.svg +++ b/.github/badges/code_issues.svg @@ -1 +1 @@ -code issuescode issues12751275 \ No newline at end of file +code issuescode issues12471247 \ No newline at end of file