% this function is the final function for carcinoma cell line
% classification that takes as input a microscopic image and outputs its
% label

% imstr is the string that signifies the name of the image file and its
% relative or absolute path respectively.
% mag is the magnification factor of the input image.
% EXAMPLE:
% label = classify_cancer_cell_line_final('C:\Users\User1\Desktop\Focus.jpg', 20)

function label = classify_cancer_cell_line_final(imstr, mag)

if ischar(mag)
    mag=str2double(mag);
end
cancer_type='NA';

load svm_undecimated_model_speed_all

no = find([10 20 40] == mag);

model = modelc{no};
mins = minsc{no};
diffs = diffsc{no};

% parameters
s = 100;
fore_ratio = 0.5;
option = 9; % option 9 is the best performing one among 1, 8 and 10
nclass = 14;

% no input image decimation

% check the image size
 %disp('Image size being checked...');
I = imread(imstr);
[r c m] = size(I);

if m == 3
    I = rgb2gray(I);
end

if r < 3096 || c < 4140
    %disp('<div> </div>')
    disp(['The image is rejected because it is too small!  ...'
        'Image size must be 3096-by-4140 or larger ']);
    label = 'Unidentified class (image size too small)';
    return
elseif r > 3096 || c > 4140
    r = r - rem(r,4);
    c = c - rem(c,4);
    I = I(1:r,1:c);
    % take the central part
    I = I((r-3096)/2:(r-3096)/2+3095,(c-4140)/2:(c-4140)/2+4139);
end

% image size
[r c] = size(I);

% check the confluency level
%disp('confluency level being checked...');
%Cmask = stdfilt_decimate_v2(I);
Cmask = logical(segmentForeBackEmMedClosingDecimate7(I,mag,mag));

% check the confluency level
conf = sum(Cmask(:))/numel(Cmask);

[rmask cmask] = size(Cmask);

conf_thresh1 = 0.1;
% conf_thresh2 = 0.9;

if conf < conf_thresh1 % || conf > conf_thresh2
    disp(['Your image has a confluency level of ',num2str(conf*100),'%. For trustworthy classification, the confluency level should be above 10%.']);
    disp('The predicted label may therefore be inaccurate.')
    disp('Your image is still being processed. In case you want to stop the processing and upload a new image, proceed with Step 1.');
    conf_thresh1 = 0;
%     x = input('Do you still want to estimate the type of the image? (y/n):','s');
%     
%     if strcmp(x,'n')
%         disp('The image is rejected because of low confluency level');
%         label = 'unidentified class (undesired confluency)';
%         return
%     end

   % disp('Processing continues...');
end


% disp('random windows being extracted...');
% extract s random windows from the image
% but use only s/frac of them at each stage

votes = cell(4,1);

sumv = zeros(nclass,1);
maxx = 0;

% divide the image into four and then process
for i = 1:2
    for j = 1:2
        
        % image patch being processed
        Ip = I((i-1)*floor(r/2)+1:i*floor(r/2),(j-1)*floor(c/2)+1:j*floor(c/2));
        
        % make the dimensions divisible by 4
        [rp cp] = size(Ip);
        Ip = Ip(1:end-rem(rp,4),1:end-rem(cp,4));
        
        Cmaskp = Cmask((i-1)*floor(rmask/2)+1:i*floor(rmask/2),(j-1)*floor(cmask/2)+1:j*floor(cmask/2));
        
        if sum(Cmaskp(:))/numel(Cmaskp) > conf_thresh1
            
            all_windows = extract_s_windows_3_furkan_v2(Ip,Cmaskp,fore_ratio,s/4,mag);
            [f,~] = covcomplex_features7_furkan_v2(Ip,option);
            
            votes{(i-1)*2+j} = zeros(nclass,1);
            
            
            
                        %disp('DT-CWT and covariances being computed...');
            % compute covariances for selected subwindows
            
            Carray = randcov_segmented7(f,all_windows,s/4);
            
                         %disp('covariances being regularized...');
            % regularize the covariance matrices
            Carray = regularize_oneC(Carray);
            
                        % disp('covariances being converted into correlation matrices...');
             %convert covariance matrices into correlation matrices
            Carray = cov_to_cor_one(Carray);
            
                         %disp('SVM prediction being performed...');
            
            d = size(Carray{1},1);
            
            testing_instance_matrix = zeros(s/4,d*(d+1)/2);
            for jjj = 1:s/4
                testing_instance_matrix(jjj,:) = vec_direct(Carray{jjj});
            end
            
            testing_label_vector = ones(s/4,1);
            
            
            
            % feature normalization before prediction
            jjj = 1:s/4;
            for iii = 1:d*(d+1)/2
                testing_instance_matrix(jjj,iii) = (testing_instance_matrix(jjj,iii) - mins(iii))/diffs(iii);
            end
            
            [predicted_label, ~, ~] = svmpredict(testing_label_vector, testing_instance_matrix, model);
            
            % majority voting
            for jjj = 1:s/4
                votes{(i-1)*2+j}(predicted_label(jjj)) = votes{(i-1)*2+j}(predicted_label(jjj)) + 1;
            end
            
            sumv = sumv + sum(votes{(i-1)*2+j},2);
            [y,ind] = sort(sumv,'descend');
            
            maxx = y(1);
            predicted_class = ind(1);
            
            maxx2 = y(2);
            predicted_class2 = ind(2);
            
            label = convert_to_string(predicted_class);
            label2 = convert_to_string(predicted_class2);
            
%             if (i-1)*2+j < 4
%                 disp('         ');
%                 disp(['The image type may be ' label ' based on the image patch ' num2str((i-1)*2+j) '/4']);
%                 disp(['The confidence rate of this decision is ' num2str(100*maxx/sum(sumv)) '%']);
%                 disp(['The second estimate for image type is ' label2 ' with the confidence rate of ' num2str(100*maxx2/sum(sumv)) '%']);
%             end
            
        else
            disp('         ');
            %disp(['The image patch ' num2str((i-1)*2+j) '/4 was not processed because of low confluency level']);
        end
        
    end
end

% confidence check
confidence_thresh = 20;
if 100*maxx/sum(sumv) < confidence_thresh || maxx == 0 %maxx < confidence_thresh %2*s/nclass
    label = 'Unidentified class (low confidence)';
    disp('The image is rejected because of low confidence level!');
    return
else
    if ~strcmp(cancer_type,'NA')
        cancer_type_found = find_cancer_type(label);
        c = 1;
        while ~strcmp(cancer_type_found,cancer_type)
            c = c + 1;
            label = convert_to_string(ind(c));
            cancer_type_found = find_cancer_type(label);
        end
        
%         disp('          ');
%         disp(['The final label is ' label ' with the confidence rate of ' num2str(100*y(c)/sum(sumv)) '%']);
% 
%         if 100*y(c)/sum(sumv) < confidence_thresh
%             disp('Select "dont know" if you are unsure about the cancer type');
%         end
%         
%     else        
%         disp('          ');
%         disp(['The final label is ' label ' with the confidence rate of ' num2str(100*maxx/sum(sumv)) '%']);
%         disp(['The second estimate is ' label2 ' with the confidence rate of ' num2str(100*maxx2/sum(sumv)) '%']);
    end
    
    disp(['Processing is finished. Your cell image is of type ' label ' (with a confidence level of ' num2str(100*maxx/sum(sumv)) '%).']);%'  with the confidence rate of ' num2str(100*maxx/sum(sumv)) '%']);
    
    disp(['The confluency level of your image is ' num2str(conf*100) '%']);
    
    disp(['The second best estimate is ' label2 ' (with a confidence level of ' num2str(100*maxx2/sum(sumv)) '%).' ]);%' with the confidence rate of ' num2str(100*maxx2/sum(sumv)) '%']);
end











