arrays - Matlab: Sum corresponding values if index is within a range -
i have been going crazy trying figure way speed up. right current code talks ~200 sec looping on 77000 events. hoping might able me speed because have 500 of these.
problem: have arrays (both 200000x1) correspond energy , position of hit on 77000 events. have range of each event separated 2 arrays, event_start , event_end. first thing position in specific range, put correspond energy in own array. need out of information, loop through each event , corresponding start/end sum energies each hit. code below:
indx_pos = find(pos>0.7 & pos<2.0); energy = hitenergy(indx_pos); i=1:n_events etotal(i) = sum(energy(find(indx_pos>=event_start(i) … & indx_pos<=event_end(i)))); end
sample input & output:
% sample input % pos , energy same length n_events = 3; event_start = [1 3 7]'; event_end = [2 6 8]'; pos = [0.75 0.8 2.1 3.6 1.9 0.5 21.0 3.1]'; hitenergy = [0.002 0.004 0.01 0.0005 0.08 0.1 1.7 0.007]'; % sample output etotal = 0.0060 0.0800 0
approach #1: generic case
one approach bsxfun
, matrix-multiplication
-
mask = bsxfun(@ge,indx_pos,event_start.') & bsxfun(@le,indx_pos,event_end.') etotal = energy.'*mask
this bit memory-hungry
if indx_pos
has lots of elements in it.
approach #2: non-overlapping start/end ranges case
one can use accumarray
special case -
%// setup id array use in accumarray later on loc(numel(pos))=0; %// fast pre-allocation scheme valids = event_end+1<=numel(pos); loc(event_end(valids)+1) = -1*(1:sum(valids)); loc(event_start) = loc(event_start)+(1:numel(event_end)); id = cumsum(loc); %// set elements zeros in hitenergy not satisfy criteria: %// pos>0.7 & pos<2.0 hitenergy_select = (pos>0.7 & pos<2.0).*hitenergy(:); %// discard elments in hitenergy_select & id have ids zeros hitenergy_select = hitenergy_select(id~=0); id = id(id~=0); %// accumulate summations done inside loop in original code etotal = accumarray(id(:),hitenergy_select);
Comments
Post a Comment