function newVesicles3D = fVesicleFilterFrames(vesicles3D)
% V2. This function checks if every vesicle corresponds to the filter
% criteria on every frame (except edge and peak-to-peak distance). If it
% doesn't fit to them on more than 'PARAM.percentOfFramesCri' frames, the
% vesicle is discarded. R2 used as fit error criterium.

global PARAM;

% changing 1/0 delFlag to extended structure version to count bad vesicles
[vesicles3D(:).delFlag] = deal(struct('pointErrCri', false, 'r2Cri', false,...
    'circularCri', false, 'widthCriMin', false, 'widthCriMax', false,...
    'amplCri', false, 'baseCri', false, 'centreDisCri', false));


% appliying non-destructive filter on vesicles on each channel and
% timeframe
for time = 1:size(vesicles3D, 3)
   for ch = 1:size(vesicles3D, 2)
      vesicles3D(:, ch, time) = fVesicleFilterNonDestructive(vesicles3D(:, ch, time));
   end
end

newVesicles3D = vesicles3D;
% going through all the vesicles
for ves = 1:size(vesicles3D, 1)
   totalTimeFramesNo = size(vesicles3D, 2)*size(vesicles3D, 3);
   vesicleDelFlag = [vesicles3D(ves, :, :).delFlag];
   % checking if maximum of the sum(on time) of all criteria delFlags
   % doesn't exceeds 'PARAM.percentOfFramesCri'
   if max([...
           %sum([vesicleDelFlag.pointErrCri])/totalTimeFramesNo,... %check
           %parameter and uncomment
           sum([vesicleDelFlag.r2Cri])/totalTimeFramesNo,...
           sum([vesicleDelFlag.circularCri])/totalTimeFramesNo,...
           sum([vesicleDelFlag.widthCriMin])/totalTimeFramesNo,...
           sum([vesicleDelFlag.widthCriMax])/totalTimeFramesNo,...
           sum([vesicleDelFlag.amplCri])/totalTimeFramesNo,...
           sum([vesicleDelFlag.baseCri])/totalTimeFramesNo,...
           sum([vesicleDelFlag.centreDisCri])/totalTimeFramesNo])...
           < PARAM.percentOfFramesCri/100
       newVesicles3D(end+1,:,:) = vesicles3D(ves, :, :);
   end
end
% leaving only passed through filter vesicles
newVesicles3D = newVesicles3D(size(vesicles3D,1):end,:,:);
fprintf('%d vesicles left after filtering on frames \n', size(newVesicles3D,1));
end

function vesicles = fVesicleFilterNonDestructive(vesicles)
% This subfunction goes through all 1D vesicles and verifies if they fit to
% all criteria. If not it append corresponding flag to .delFlag

global PARAM;

for i = 1:length(vesicles)
   % if all points are properly fitted? satisfies pointErrCri
   if max(max(vesicles(i).pointerror)) > PARAM.pointErrCri/100
       vesicles(i).delFlag.pointErrCri = true;
   end
   
   % if satisfies total fit error criteria
   if vesicles(i).r2 > PARAM.r2Cri
       vesicles(i).delFlag.r2Cri = true;
   end
   
   % if satisfies to the circularity criteria
   circularity = vesicles(i).sx / vesicles(i).sy;
   if circularity < PARAM.circularCri || circularity > 1/PARAM.circularCri
       vesicles(i).delFlag.circularCri = true;
   end
   
   % if satisfies to the minimal width criteria
   if min(vesicles(i).sx, vesicles(i).sy) < PARAM.widthCriMin 
       vesicles(i).delFlag.widthCriMin = true;
   end
   
   % if satisfies to the maximal width criteria
   if max(vesicles(i).sx, vesicles(i).sy) > PARAM.widthCriMax 
       vesicles(i).delFlag.widthCriMax = true;
   end
   
   % if satisfies to the minimal amplitude criteria
   if vesicles(i).a < PARAM.amplCri 
       vesicles(i).delFlag.amplCri = true;
   end
   
   % if satisfies to the maximal baseline height criteria
   if vesicles(i).b > PARAM.baseCri 
       vesicles(i).delFlag.baseCri = true;
   end
   
   
   % if fitted maximum and observed maximum are close enough 
   centreDistance=sqrt( (vesicles(i).m-vesicles(i).x0)^2 + (vesicles(i).n-vesicles(i).y0)^2);
   if centreDistance > PARAM.centreDisCri 
       vesicles(i).delFlag.centreDisCri = true;
   end
   
end

end
