function [affinity, dist] = getL2DistanceAffinityLoc(features, ...
  patchIndexes, relLocs, affinity)
% [affinity, dist] = getL2DistanceAffinity(features);
% [affinity, dist] = getHistogramIntersectionAffinity(features);
disp('Calculating initial affinities');
affinity = getChiSqDistAffinity(features, 50);
% affinity = getEucSqDistAffinity(features, 50);
dist = affinity;
% Reduce the affinity of patches from the same image.
disp('adjusting affinities of patches from same images');
% affinity = adjustAffinityForSameImage(affinity, patchIndexes);
disp('adjust affinities for location');
affinity = adjustAffinityForLocation(affinity, relLocs);
end

function affinity = getChiSqDistAffinity(features, bandwidth)
dist = slmetric_pw(features', features', 'chisq');
affinity = exp(-dist / bandwidth);
end

function affinity = getEucSqDistAffinity(features, bandwidth)
dist = slmetric_pw(features', features', 'sqdist');
meanVal = mean(dist(:));
stddev = std(dist(:));
thresh = max(meanVal - stddev, 0.5 * meanVal);
dist(dist>thresh) = inf;
affinity = exp(-dist / bandwidth);
end

function affinity = adjustAffinityForSameImage(affinity, patchIndexes)
for i = 1 : size(patchIndexes, 1)
  imgId = patchIndexes(i, 1);
  sameImgPatches = find(patchIndexes(:, 1) == imgId);
  affinity(i, sameImgPatches) = affinity(i, sameImgPatches) / 2;
  affinity(sameImgPatches, i) = affinity(sameImgPatches, i) / 2;
  affinity(i, i) = 1;
end
end

function affinity = adjustAffinityForLocation(affinity, relLocs) 
locs = getLocationArray(size(affinity, 1), relLocs);
locDist = slmetric_pw(locs', locs', 'sqdist');
meanVal = mean(locDist(:));
stddev = std(locDist(:));
thresh = max(meanVal - stddev, 0.5 * meanVal);
locDist(locDist>thresh) = inf;
w = exp(-100 * locDist);
affinity = affinity .* w;
end

function locs = getLocationArray(n, relLocs)
locs = zeros(n, 2);
locInds = 0;
for i = 1 : length(relLocs)
  num = size(relLocs{i}, 1);
  if size(relLocs{i}, 2) > 2
    x = relLocs{i}(:, 1:2:end);
    x = mean(x, 2);
    y = relLocs{i}(:, 2:2:end);
    y = mean(y, 2);
    locs(locInds+1 : locInds+num, :) = [x y];
  else
    locs(locInds+1 : locInds+num, :) = relLocs{i};
  end
  locInds = locInds + num;
end
end
