load([PROCESSING_DIR 'CLUSTER_PROCESSING_INFO'], 'clusterInformation');
load([PROCESSING_DIR 'ALL_DATA'], 'trainSetPos', 'trainSetNeg', ...
  'positivePatches', 'selectedClusters', 'params');
load([PROCESSING_DIR 'NEG_CALC_FEATURES'], 'negFeatures', ...
  'negativePatches');
load([PROCESSING_DIR 'POSITIVE_PATCHES'], 'positivePatchesPerImg', ...
  'locationInfo');
load([PROCESSING_DIR 'FIG_PATCH_CLUSTERS_REF'], 'assignedClust', ...
  'centers', 'PARAMS', 'selectedClusters', 'positivePatches', ...
  'allFeatures', 'patchIndexes');

%%

patchInfos.features = clusterInformation.allFeatures;
patchInfos.voteLocations = getPatchVoteLocations(locationInfo, ...
  patchIndexes);
patchInfos.locationWts = [1 1 1 1];

minMembers = 3;
patchInfos.costFactors.appCostFactor = 1;
patchInfos.costFactors.locCostFactor = 4;
patchInfos.costFactors.memCostFactor = 30;

%%

global iterIndex;
iterIndex = 1;
figLocations = [PROCESSING_DIR 'clustRefinement2/'];
mkdir(figLocations);

newAssignedClust2 = cell(size(selectedClusters));
for i = 1 : length(selectedClusters)
  chosenCluster = i;
  currClust = selectedClusters(chosenCluster);
  posInds = find(clusterInformation.assignedClusters==currClust);
  iterNo = 0;
  while true
    iterNo = iterNo + 1;
    posFeatures = clusterInformation.allFeatures(posInds, :);
    features = [posFeatures; negFeatures];
    labels = [ones(length(posInds), 1); ...
      ones(size(negFeatures, 1), 1) * -1];
    disp('Training SVM');
    model = mySvmTrain(labels, features, '-s 0 -t 0 -c 1');

    [predictedLabels, accuracy, posDec] = mySvmPredict( ...
        ones(size(clusterInformation.allFeatures, 1), 1), ...
        clusterInformation.allFeatures, model);

    %Evaluate high scored ones

    patchImgs = unique(patchIndexes(posInds, 1));
    allImgs = patchIndexes(:, 1);
    [toDiscard, unused] = ismember(allImgs, patchImgs);
    filtered = find(toDiscard < 1);
    posDec = posDec(filtered);
    filteredImgs = allImgs(filtered);
    [unused, highInds] = sort(posDec, 'ascend');
    filteredSorted = filtered(highInds);
    filteredImgsSorted = filteredImgs(highInds);
    [filtUnique m n] = unique(filteredImgsSorted);
    filteredSortedFinal = filteredSorted(sort(m));

    appDists = getDistancesFromCenter(posFeatures);
    patchVoteLocations = getPatchVoteLocations(locationInfo, ...
      patchIndexes);
    [unused, bestPoints] = getBestDistance(patchVoteLocations(posInds), ...
      patchInfos.locationWts);
    locDists = getDistancesFromCenter(bestPoints);
    [unused, sortAppInds] = sort(appDists, 'descend');
    [unused, sortLocInds] = sort(locDists, 'descend');
    toSelect = min(floor(length(posInds) / 2), 3);
    selected = [sortAppInds(1:toSelect); sortLocInds(1:toSelect)];
    selected = posInds(unique(selected));
    fixedPos = setdiff(posInds, selected);

    maxToProcess = 10;
    toInclude = min(maxToProcess - length(selected), ...
      length(filteredSortedFinal));
    toEval = setdiff(filteredSortedFinal(end-toInclude+1:end), posInds);

    candidates = [fixedPos; selected; toEval];
    fixed = zeros(size(candidates));
    fixed(1:length(fixedPos)) = 1;
    disp('Getting the min cost combinations');
    [minMemb, minCost] = getMinCostCombination(candidates, ...
      fixed, patchInfos, minMembers);
    newPosInds = candidates(minMemb>0);

    fig1 = figure(1); clf;
    displayPatches(positivePatches(newPosInds), params);
    figure(2); clf;
    displayPatches(positivePatches(candidates(minMemb<1)), params);
    figure(3); clf;
    newOnes = setdiff(candidates(minMemb>0), posInds);
    displayPatches(positivePatches(newOnes), params);
    pause(1);
%     saveas(fig1, [figLocations sprintf('%d_%d.jpg', currClust, iterNo)],...
%       'jpg');
%     keyboard;

    if isempty(setdiff(posInds, newPosInds)) && ...
        length(posInds) == length(newPosInds)
      break;
    end
    posInds = sort(newPosInds);
  end
  newAssignedClust2{i} = newPosInds;
end
save([PROCESSING_DIR 'ASSN_CLUST2'], 'newAssignedClust2');

%% Get all the unique clusters

for i = 1 : length(newAssignedClust2)
  fig1 = figure(1); clf;
  clustInds = newAssignedClust2{i};
  disp(patchIndexes(clustInds, 1)');
  displayPatches(positivePatches(clustInds), params);
  pause;
end

%% Calculate costs for each cluster

clusterCosts = zeros(size(newAssignedClust));
for i = 1 : length(newAssignedClust)
  candidates = newAssignedClust{i};
  membs = ones(size(candidates));
  clusterCosts(i) = getClusterCost(candidates, membs, patchInfos);
end


%% Collapse all new clusts into a single array removing the dups

[unused, costOrder] = sort(clusterCosts, 'ascend');
uniqueClusts = zeros(size(assignedClust));
uniqueSelected = [];
for i = 1 : length(costOrder)
  clustInds = newAssignedClust{costOrder(i)};
  unClVals = uniqueClusts(clustInds);
  if length(unique(unClVals)) ~= 1
    disp('Patch sharing across clusters');
  elseif sum(unClVals) < 1
    uniqueClusts(clustInds) = costOrder(i);
    uniqueSelected = [uniqueSelected costOrder(i)];
  end
end
uniqueClusts(uniqueClusts==0) = max(uniqueSelected) + 1;

%% Save information

saveDir = [PROCESSING_DIR 'bedRefinedData/'];
mkdir(saveDir);

centers = calculateClusterCenters(uniqueSelected, uniqueClusts, ...
  clusterInformation.allFeatures);
saveInfoForWarpProcessing(saveDir, uniqueClusts, ...
  centers, uniqueSelected, clusterInformation.allFeatures, ...
  positivePatches, trainSetPos, trainSetNeg, params);

  
%% Write out all the patches

outDir = [PROCESSING_DIR 'bedRefinedClusts/'];
mkdir(outDir);
parfor i = 1 : length(uniqueSelected)
  clustInds = find(uniqueClusts == uniqueSelected(i));
  namePrefix = sprintf('%d_%d_', i, uniqueSelected(i));
  writeOutPatches(positivePatches(clustInds), outDir, ...
    params.patchCanonicalSize, namePrefix);
end


%% Compute the minimum cost combination


global iterIndex;
iterIndex = 1;
figure;
plot(0, 0, '.r');
hold on;
candidates = candidates(1:14);
fixed = zeros(size(candidates));
fixed([1 4 7 9]) = 1;
tic;
[minMemb, minCost] = getMinCostCombination(candidates, ...
  fixed, patchInfos, minMembers);
toc;
hold off;
minMemb'
minCost

%% Experiments with the costs

cands = find(clusterInformation.assignedClusters == 1);
membs = ones(size(cands));

dsts = getDistancesFromCenter(clusterInformation.allFeatures(cands, :));
[~, inds] = sort(dsts);
clCosts = [];
appCosts = [];
locCosts = [];
memCosts = [];
for i = 1 : length(inds)
  membs = ones(size(cands));
  membs(inds(i)) = 0;
  [clCosts(i), appCosts(i), locCosts(i), memCosts(i)] = ...
    getClusterCost(cands, membs, patchInfos);
end
clf;
plot(clCosts, 'r');
hold on;
plot(appCosts, 'b');
plot(locCosts, 'g');
plot(memCosts, 'm');
hold off;

