from High Speed PIV and Hotwire post processing by Anurag
High Speed PIV and hotwire post processing routines

findslowregs(frame,reg_xl, reg_yl, arealim, uthresh, connectregs)
function findslowregs(frame,reg_xl, reg_yl, arealim, uthresh, connectregs)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                                                  %%
%%   Copyright (C) 2005-2007  Anurag Singh                                                          %%
%%                                                                                                  %%
%%       This program/code snippet/file (hence forth refered as "library")                          %%
%%       is free software; you can redistribute it and/or                                           %%
%%       modify it under the terms of the GNU Lesser General Public                                 %%
%%       License as published by the Free Software Foundation; either                               %%
%%       version 2.1 of the License, or (at your option) any later version.                         %%
%%                                                                                                  %%
%%       This library is distributed in the hope that it will be useful,                            %%
%%       but WITHOUT ANY WARRANTY; without even the implied warranty of                             %%
%%       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                          %%
%%       Lesser General Public License for more details.                                            %%
%%                                                                                                  %%
%%       You should have received a copy of the GNU Lesser General Public                           %%
%%       License along with this library; if not, write to the Free Software                        %%
%%       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                  %%
%%                                                                                                  %%
%%   FILENAME:                                                                                      %%
%%      findslowregs.m                                                                              %%
%%                                                                                                  %%
%%   AUTHOR:                                                                                        %%
%%                                                                                                  %%
%%      Anurag Singh,                                                                               %%
%%      MS, 2007                                                                                    %%
%%      Aerospace Engineering & Mechanics                                                           %%
%%      University of Minnesota - Twin Cities.                                                      %%
%%      Minneapolis, MN 55455 (USA)                                                                 %%
%%                                                                                                  %%
%%      (currently working at: Exa Corporation, Burlington, MA 01803)                               %%
%%                                                                                                  %%
%%   CONTACT/EMAIL:                                                                                 %%
%%                                                                                                  %%
%%      anurag@aem.umn.edu                                                                          %%
%%      anurag9@gmail.com                                                                           %%
%%                                                                                                  %%
%%   SOURCE CONTROL INFORMATION:                                                                    %%
%%      None (since I was planning on putting it under source control since it has                  %%
%%      reached the critical file system size. Would be a good thing to put it under                %%
%%      source control while making changes.                                                        %%
%%                                                                                                  %%
%%   DESCRIPTION:                                                                                   %%
%%                                                                                                  %%
%%       Need to add                                                                                %%
%%                                                                                                  %%
%%                                                                                                  %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




   global numregions newregid newregion slowregion swfrm nuidfrm tagidstack mergregid newregion
   
   markregions(frame,arealim,uthresh);
   disp(['Number of regions before connecting = ',num2str(numregions)]);

   if(connectregs == 1)

      swfrm = nuidfrm;       % store the original found regions for comparison later

      % Initialize merge id table and new idtag stack
      tagidstack = (numregions+1:numregions+numregions);          % Create new id tag stack
      mergregid = zeros(numregions);
      newregion  = newregion * 0;

      %Call the connection routine to join the close regions into one region


      connect_regions(reg_xl, reg_yl);

      temp = (newregion - numregions);
      temp = temp .* (temp > 0);
      slowregion = temp;

      newregid = numregions - size(tagidstack,2) ; % the difference between the two would be the new number or regions after joining
      disp(['New number of regions after connecting = ',num2str(newregid)]);
   else
   
      slowregion = nuidfrm;   
   
   end
return;



function []=markregions(frame,arealim, uthresh)
% This function identifies the vortex cores

   global NX NY idfrm markfrm pointcnt u_norm piv_ustd
   global ufrm ufrm1 nuidfrm numregions

   idfrm      = ufrm * 0;
   markfrm    = ufrm * 0;
   pointcnt   = pointcnt * 0;
   numregions = 0;

   ufrm  = squeeze(u_norm(frame,:,:));
   ufrm  = ufrm .* (ufrm < -uthresh*piv_ustd);                % extract only slow speed regions
   ufrm1 = ufrm;

   idtag  = 0;

   %disp(['Identifying slow speed regions in frame # ' num2str(frame) ' ...']);
   idtag   = tagregions(idtag, arealim);
   nuidfrm = idfrm;
   idfrm   = 0 * idfrm;

   numregions = idtag;
   %disp(['done, Total regions identified = ' num2str(idtag)]);


return;



function [idtag]=tagregions(idtag, arealim)

   global NX NY idfrm markfrm pointcnt
   global ufrm

   while(any(any(markfrm == 0)) && any(any(ufrm~=0))) % do this until entire sw array becomes zero or all the regions have been identified


      idtag = idtag + 1;
      markfrm = 0 * markfrm;                 % zero out all previous markings
      minu = min(min(ufrm));

      [seedi, seedj] = find(ufrm==minu);

      growregion(seedi(1), seedj(1),idtag);     % Pass on only the first element in case there are two peaks with identical values
      
      % This will mark all the region around the minu by idtag in array idfrm
      % the boundary of the region will be marked by -idtag

      deleteregion(idtag); % this will zero-out all the regions marked by idtag in swfrm sothat other regions could be identified.

      %dbstop in findslowregs.m at 86
      
      [tx ty] = find(idfrm == idtag);
      pointcnt(idtag) = size(tx,1);      % no. of points identified with tag idtag

      % Remove regions with less than arealimit points   
      if(pointcnt(idtag) <= arealim)
        idfrm = idfrm .* (~(idfrm ==idtag)) .* (~(idfrm ==-idtag)); % delete all marks corresponding to idtag 
        idtag = idtag  - 1;
        %disp([' ... Deleted identified region at (',num2str(seedi(1)),',',num2str(seedj(1)),') due to area limit']);
      else
        %disp([' ... Identified region with peak at (',num2str(seedi),',',num2str(seedj),')']);
      end

   end
return;







function []=growregion(seedi, seedj, idtag)

   global NX NY idfrm ufrm markfrm pointcnt


%   idtag
%   dbstop if error
   if((seedi < 1 || seedi > NX || seedj < 1 || seedj > NY)) % check if the index limits are within bounds
      %btag = 1;
      return
   end

   

   if(markfrm(seedi,seedj) ~= 0)  % check if the cell has already been visited, return if true
      return;
   end

   %disp(['   Visiting Cell (' num2str(seedi) ',' num2str(seedj) ')']);

   if((ufrm(seedi,seedj) == 0) )        % Check if this cell has a zero value meaning its the boundary of the current region
%      idfrm(seedi,seedj)   = -idtag;        % if true apply mark and visit the neighboring cells
      markfrm(seedi,seedj) = 1;    % mark the cell visited
      return;
   end

   % at this point this cell has not been visited neither has it been marked check the u values
   %if((swfrm(seedi,seedj) >= ll && swfrm(seedi,seedj) <= ul) )        % Check if this cell is valid pointhas a non-zero swirl value

   if((ufrm(seedi,seedj) ~= 0) )        % Check if this cell has a non-zero swirl value

      idfrm(seedi,seedj)   = idtag;        % if true apply mark and visit the neighboring cells
      markfrm(seedi,seedj) = 1;    % mark the cell visited
      %pointcnt(idtag)      = pointcnt(idtag) + 1;


  % C is the central cell and the surrounding cells are marked as following:
  %             
  %            4  3  2
  %            5  C  1
  %            6  7  8
  %
  %      C = (m,n)
         growregion(seedi-1, seedj  , idtag);
         growregion(seedi+1, seedj  , idtag);
  
         growregion(seedi  , seedj-1, idtag);
         growregion(seedi  , seedj+1, idtag);
  
         growregion(seedi-1, seedj-1, idtag);
         growregion(seedi+1, seedj-1, idtag);
  
         growregion(seedi-1, seedj+1, idtag);
         growregion(seedi+1, seedj+1, idtag);
   end

return;






% This routine is called when all the slow speed regions is identified and now regions very close are joined to form one region
% The two regions are joined if they are separated in the streamwise and spanwise direction by a certain number of cells
% reg_xl, is the limit in the streamwise direction
% reg_yl is the limit in the spanwise direction
% the two regions are joined diagonally by a single line of cells
% Also the regions are joined only if there are no identified cores between them
% the newly joined regions acquire a new idtag which is higher than max number of regions identified, this number is increased serially
% In case a particular region is not joined to any and thus retains it old idtag would be given a new
% one in the new sequece.
% finally after all the regions have been visited idtags shifted back to start from 1
% After above step we have newly identified regions (after joining if any required) serially


function connect_regions(reg_xl, reg_yl) % reg_xl & reg_yl define the filter size in establishing connection

global nuidfrm numregions mergregid


region     = nuidfrm;

for regid=1:numregions        % do the connection for all the regions

  [X Y] = find(region==regid);           % get the indices of all regions which are tagged with regid i.e. one region at a time
   
   for m=1:size(X)              % scan the entire region for proximity to another region and make joints if needed
      find_connected_regions(X(m), Y(m), reg_xl, reg_yl, region, regid);
   end
   
   % now joints has been established remove holes if any 
   %
   %  Needs to be coded
   %
end


updateregions(region);     % mark the original regions also by their new idtag


return;






 % searches the boundary of one region and concentrates on one only at a time
 % routine connect_region calls this repeatedly for covering all the regions
 
function find_connected_regions(seedi, seedj, reg_xl, reg_yl, region, regid)


   if(bndry_check(seedi, seedj, region, regid) == 0) % check if its a boundary element or not, if not return
      return;
   end
   
   % At this point we are within array bounds and its a boundary element, check for neaibouring regions
   % and find if they should be joined with the current one
   
   % get the filter grid containing neibouring regions

   filtregid = getfiltergrid(seedi, seedj, reg_xl, reg_yl, region, regid);

   
   % mark down all the region ids which fall in the filter for merging later
   % Only after this step we have the regions which actually needs to be joined
   % sAnd finally join the two regions with the newregid in the newregion array

   joinregion(filtregid, seedi, seedj, region, regid);
   
return;












function check=bndry_check(x, y, region, regid)

global NX NY

% establish the boundaries of the cell (x,y)
xmin = x - 1;  if(xmin < 1 ); xmin = 1 ; end;
xmax = x + 1;  if(xmax > NX); xmax = NX; end;

ymin = y - 1;  if(ymin < 1 ); ymin = 1 ; end;
ymax = y + 1;  if(ymax > NY); ymax = NY; end;



% region(x,y) is a boundary element if and only if it is surrounded on all the sides
% i.e. all the cells must be marked by regid in the above defined grid

[X Y]=find((region(xmin:xmax,ymin:ymax) ~= regid));   

if(isempty(X))
   check = 0;
else
   check = 1;
end

return;






function [filtgrid] = getfiltergrid(seedi, seedj, reg_xl, reg_yl, region, regid)

global NX NY
global fltx flty mergregid



xmin = seedi - reg_xl;  if(xmin < 1 ); xmin = 1 ; end
ymin = seedj - reg_yl;  if(ymin < 1 ); ymin = 1 ; end

xmax = seedi + reg_xl;  if(xmax > NX); xmax = NX; end
ymax = seedj + reg_yl;  if(ymax > NY); ymax = NY; end


filtgrid = region(xmin:xmax,ymin:ymax);               % copy all the elements in this grid

[x y] = find(mergregid(:,regid));          % Find if there are any joints associated with regid

% get all the elements which are not part of the region or a joint between two region
if(isempty(x))          %The region has not been connected previously before to any other region -> no joints
   filtgrid = filtgrid .* (~(filtgrid == regid));
%   disp(['This region never connected, regid = ',num2str(regid),' cell (x,y) = (',num2str(seedi),',',num2str(seedj),')']);

else                   % this region has been connected previously and all it's joints must be considered
   filtgrid = filtgrid .* (~(filtgrid == regid)) .* (~(filtgrid == mergregid(x(1),y(1))));
end

% find out the indices of the non zero elements in the filtered region
temp = region * 0;
temp(xmin:xmax, ymin:ymax) = filtgrid;
[fltx flty] = find(temp ~= 0);   % this gives the co-ordinates of the cells of regions to be joined in (fltx, flty)


return












function joinregion(filtregid, x, y, region, regid)

global fltx flty


if(isempty(fltx))       % return if there is nothing to be joined
   %disp('Nothing to join');
   return;
end

% At this point fltx is non-zero implying there are other regions in the vicinity of the current region
% which may or may not be connected previously, the two must be connected

X = fltx;
Y = flty;


% get all the tagged regions this is inefficient way to do this, its okay if there aint many regions to be joined

for m=1:size(X) % join each non-zero element to the original seed
   
   tempregid = update_merge_table(regid, region(X(m),Y(m)), region); % update the mergetable and get the new idtag   
   
   %['in join, tempregid =', num2str(tempregid),', V(m) = ',num2str(V(m)), ...
   %',  merg(',num2str(m),',',num2str(regid),') = ', num2str(mergregid(m,regid))]

   % join all the cells to cell of the original region
   xt = X(m);
   yt = Y(m);
   
   %['in join,  ' num2str(tempregid)]
   
   mergepoints(xt, yt, x, y, region, regid, tempregid);        % establish the joint between the two points

end


return









% This function updates the mergeid table appropriately and gives the new tempregid for creating joints between regions regid1 & regid2
function tempregid = update_merge_table(regid1, regid2, region)

global mergregid newregion

%%
% now copy columns and rows corresponding to regid1 & regid2
temp = mergregid * 0 ;
temp(regid1,:) = mergregid(regid1,:); temp(:,regid1) = mergregid(:,regid1);
[x1 y1] = find(temp);      % This gives co-ordinates in merge idtable of to which regid1 is connected

temp = temp*0;
temp(regid2,:) = mergregid(regid2,:); temp(:,regid2) = mergregid(:,regid2);
[x2 y2] = find(temp);      % This gives co-ordinates in merge idtable of to which regid2 is connected

%disp(['idtags (regid1 regid2) = ',num2str(regid1),', ',num2str(regid2)]);
%[x1 y1 x2 y2]



%% 4 possibilities
%%    reg1 reg2
%% 1-   N  N
%% 2-   N  C
%% 3-   C  N
%% 4-   C  C
% 1 would require a new tag and updating the table
% 2 & 3 would entail using the tag id from the one which is connected and updating the entire table
% 4 would require analysis as whether reg1 is should be picked or reg2. This is the only case where newregion array needs to be updated also

   
if(isempty(x1) && isempty(x2))               %Case 1, none connected before
   % Get a new idtag, and update the mergeid table (only 2 cells need be updated
   tempregid=idstack('pop',0);        % Get a new idtag from the new idtag pool/stack, 2nd argument is dummy
   
   mergregid(regid1,regid2) = tempregid;
   mergregid(regid2,regid1) = tempregid;
   
   

elseif(isempty(x1) && ~(isempty(x2)))       %Case 2, regid1 not connected, regid2 connected
   % Use regid2's tag and update the table
   tempregid = mergregid(x2(1),y2(1));
   
   mergregid(regid1,regid2) = tempregid;
   mergregid(regid2,regid1) = tempregid;

   % update the mergregtable further for the other regions which are connected to region2
   for m=1:size(x2)
      mergregid(regid1,x2(m)) = tempregid;
      mergregid(x2(m),regid1) = tempregid;
   end

elseif(~(isempty(x1)) && (isempty(x2)))     %Case 3, regid1 connected, regid2 not connected
   % Use regid1's tag and update the table
   tempregid = mergregid(x1(1),y1(1));
   
   mergregid(regid1,regid2) = tempregid;
   mergregid(regid2,regid1) = tempregid;

   % update the mergregtable further for the other regions which are connected to region1
   for m=1:size(x1)
      mergregid(regid2,x1(m)) = tempregid;
      mergregid(x1(m),regid2) = tempregid;
   end

elseif(mergregid(x1(1),y1(1)) == mergregid(x2(1),y2(1)))  % no table update required in this case
   tempregid = mergregid(x2(1),y2(1));

elseif(~(isempty(x1)) && ~(isempty(x2)))    %Case 4, regid1 connected, regid2 connected
   
   %Find which region has a smaller tag, and use that to update the tables
   % Also update the newregion array
   % Also update the newregid counter, since two sets of already connected regions are futher connected.
   
   idv1 = mergregid(x1(1), y1(1));           % get the value of the idtags for regid1
   idv2 = mergregid(x2(1), y2(1));           % get the value of the idtags for regid1

  % [(isempty(x1)) (isempty(x2))]
  % [idv1 idv2]

   if(idv1 < idv2)                           % Use region1 tag
      tempregid = mergregid(x1(1),y1(1));
      
      % update all the connected regions in region2 to region1 tag
      mergregid(regid1,regid2) = tempregid;
      mergregid(regid2,regid1) = tempregid;
      
      % update the mergregtable further for the other regions which are connected to region1s
      for m=1:size(x1)
         mergregid(regid2,x1(m)) = tempregid;
         mergregid(x1(m),regid2) = tempregid;
      end
      
      %update newregion array, i.e, mark all the joints corresponding to region2 to the new tag
      temp = idv1 * (newregion == idv2);      
      newregion = newregion .* (~(temp)) + temp ;
      
      % Update the new idtag stack, i.e send the idv2 to the pool of available tags
      idstack('push',idv2);
      return;
      
   elseif(idv1 > idv2)                      % Use region2 tag

      tempregid = mergregid(x2(1),y2(1));
      
      % update all the connected regions in region1 to region2 tag
      mergregid(regid1,regid2) = tempregid;
      mergregid(regid2,regid1) = tempregid;

      % update the mergregtable further for the other regions which are connected to region2

      for m=1:size(x2)
         mergregid(regid1,x2(m)) = tempregid;
         mergregid(x2(m),regid1) = tempregid;
      end

      temp = idv2 * (newregion == idv1);      
      newregion = newregion .* (~(temp)) + temp ;
      
      % Update the new idtag stack, i.e send the idv2 to the pool of available tags
      idstack('push',idv1);

   end
else
disp('ERROR in update merge table');
end


return;




% This functions simulates a pool of available id tags, and stores them in the poll or returns them to the calling program
% tagidstack must be initiialized outside this routine before making use of it

function newregid=idstack(operation,newregid)

global tagidstack

   switch operation
   case 'pop'
      newregid = tagidstack(1);
      tagidstack(1) = [];
      %disp(['Generated new id tag = ',num2str(newregid)])
      return;

   case 'push'
      tagidstack = [newregid tagidstack];
      %disp(['Added to the stack, id tag = ',num2str(newregid)])
      return;
   otherwise
      disp('ERROR: Wrong Stack Operation for newregid stack')
   end 

return












function []=updateregions(region)
   %zero out the region in frame swfrm marked by idtag in idfrm

global newregid newregion mergregid
   
   for m=1:size(mergregid,1)
     
      temp = mergregid * 0 ;
      temp(m,:)      = mergregid(m,:);
      temp(:,m)      = mergregid(:,m);
      [t1 t2] = find(temp);

      %[t1 t2] = find(mergregid(:,m)); % get the new idtag corresponding to old region 'm'
      
      % check if t1 is empty, if true, it means this region is not connected to anyone and
      % old tags were retained. These should be renewed
      
      if(isempty(t1))
         tempregid = idstack('pop',0);        % Get a new idtag from the new idtag pool/stack
     
      else     % This region has been connected previously, pick its id tag from the merge table and mark the region
         tempregid = mergregid(t1(1),t2(1));
      end


   %['in update, tempregid =', num2str(tempregid)]%, ', newregion(59,23)=', num2str(newregion(59,23))]%,', t3(1) = ',num2str(t3(1)), ...
   %',  merg(',num2str(t1(1)),',',num2str(t2(1)),') = ', num2str(mergregid(t1(1),t2(1)))]
      
      newregion = newregion + tempregid * (region == m);       % Mark this region with the new tag
      
   end
return;





function []=deleteregion(idtag)
   %zero out the region in frame swfrm marked by idtag in idfrm
   global idfrm ufrm

   ufrm = ufrm.*(~(idfrm(:,:)==-idtag)).* (~(idfrm(:,:)==idtag)); 
return;

















function mergepoints(xt,yt, x, y, region, regid, tempregid)

global newregion ufrm1

%disp('in mergepoint');
%[xt yt x y]

if((xt == y) && (yt == y))
   return;
end

if(region(xt,yt) == regid) 
   return;
end


% mark the region (do so only if its not part of any other parent regions
if(region(xt,yt) == 0)
   newregion(xt,yt) = tempregid;
   newregion(xt,yt);
end

% call the routine again depending with updated xt, yt
dx = sign(x-xt);  % increment 1 or -1 depending on where x is
dy = sign(y-yt);  % increment 1 or -1 depending on where y is

mergepoints(xt+dx, yt+dy, x, y, region, regid, tempregid);

return;































Contact us at files@mathworks.com