function [M] = AllRelativePatchNormXCorr_FlipPermute(I,options);
% function [M] = AllRelativePatchNormXCorr_FlipPermute(I,options);
%  
 d.patchsize = 7;
 d.LRrange = 25;
 d.UDrange = 0;% 7;
 d.permute = 1:size(I,3);
% d.bMaximalSupportSuppression = 0;  % Symmetry must be supported by more than one layer.
 if(nargin < 2), options = [];, end;
 options = ResolveMissingOptions(options,d);
 % options 
 patchsize = options.patchsize;
 Iflip = I(:,:,options.permute); 
 ks = patchsize * patchsize * size(I,3);
 nOri = size(I,3);
 I = padimage(I,ceil(patchsize/2),'symmetric');
 for iOri = 1:nOri
   LocalMean(:,:,iOri) = conv2(ones(patchsize,1),ones(1,patchsize),I(:,:,iOri),'same');
   DENOM_ONESIDE(:,:,iOri) = conv2(ones(patchsize,1),ones(1,patchsize),I(:,:,iOri).*I(:,:,iOri),'same');
 end
 LocalMean = sum(LocalMean,3);
 DENOM_ONESIDE = sum(DENOM_ONESIDE,3);
 I = unpadimage(I,ceil(patchsize/2));
 LocalMean = unpadimage(LocalMean,ceil(patchsize/2));
 LocalMean = LocalMean / ks;
 DENOM_ONESIDE = unpadimage(DENOM_ONESIDE,ceil(patchsize/2));
 DENOM_ONESIDE = DENOM_ONESIDE - ks .* (LocalMean.^2);
 MAX_OF_DENOM = max(DENOM_ONESIDE(:));
 M = zeros(size(I,1),size(I,2),2*options.UDrange+1,options.LRrange+1);
 I = padimage(I, patchsize, 'symmetric');
 Iflip = padimage(Iflip, patchsize, 'symmetric');
 LocalMean = padimage(LocalMean, patchsize, 'symmetric');
 DENOM_ONESIDE = padimage(DENOM_ONESIDE,patchsize,'symmetric');
 if(any(DENOM_ONESIDE(:) < 0))
   % keyboard;
   DENOM_ONESIDE = abs(DENOM_ONESIDE);
 end  
 if(0)
   LowerBoundDenom = percentile(DENOM_ONESIDE(:),.2,1);
   if(LowerBoundDenom == 0)
     LowerBoundDenom = 1/100 * max(D_3(:));
   end
   DENOM_ONESIDE = max(DENOM_ONESIDE,LowerBoundDenom);
 end
 DENOM_ONESIDE = DENOM_ONESIDE + eps;
 meanI = mean(I(:));
 for i = -options.UDrange:options.UDrange
   fprintf('row %d of %d\r',i+options.UDrange+1, 2*options.UDrange+1);
   for j = 0:options.LRrange
     SHIFTI = TranslateIm(Iflip,[i,j],meanI);
     SHIFTMean = TranslateIm(LocalMean,[i,j],meanI);
     SHIFTDenom = TranslateIm(DENOM_ONESIDE,[i,j],MAX_OF_DENOM);
     D_3 = (sqrt(sum(DENOM_ONESIDE .* SHIFTDenom,3)));
     D_3 = RemoveBoundarySignal(D_3,i,j,patchsize,MAX_OF_DENOM);
     for iOri = 1:nOri
       N(:,:,iOri) = SymmetricPatchDotProduct(I(:,:,iOri),SHIFTI(:,:,iOri),options);
     end
     N_3 = sum(N,3);
%     if (options.bMaximalSupportSuppression);
%        N_3 = N_3 - max(N,[],3);
%     end
     N_3 = N_3 - ks * sum(LocalMean.*SHIFTMean,3);
%     M(:,:,i+options.UDrange+1,j+1) = unpadimage(TranslateIm(N_3 ./ D_3,[0,-floor(j/2)-floor(patchsize/2)]),patchsize);
     M(:,:,i+options.UDrange+1,j+1) = unpadimage(TranslateIm(N_3 ./ D_3,[0,-floor(j/2)]),patchsize);
   end
 end
 fprintf('row %d of %d\n',i+options.UDrange+1, 2*options.UDrange+1);
% z = M(:,:,1,1);
% keyboard


function N_3 = RemoveBoundarySignal(N_3,transi,transj,patchsize,fillval);
sz = size(N_3);
for i = (transi - patchsize):(transi + patchsize)
  for x = 1:sz(2)
    y = mod( (i-1),sz(1))+1;
    N_3(y,x) = fillval;
  end  
end
for j = (transj - patchsize):(transj + patchsize)
  for y = 1:sz(1);
    x = mod( (j-1),sz(2))+1;
    N_3(y,x) = fillval;
  end
end

function Iflip = flipimage(I,options);
if options.bFlipLR
  Iflip = Iflip(:,end:-1:1,:);
end
if options.bFlipUD
  Iflip = Iflip(end:-1:1,:,:);
end 

