% SedCTimage MATLAB GUI for sediment CT scans collected on a medical CT
% scanner and products of SedCT
% Developed 2014, Brendan T. Reilly, Oregon State University
% Last modified to fix issue with Mac vs. PC directories, March 11, 2022
% Please cite:
% Reilly, B.T., Stoner, J.S., Wiest, J., (2017) 
% SedCT: MATLAB™ tools for standardized and quantitative 
% processing of sediment core computed tomography (CT) data 
% collected using a medical CT scanner. Geochem. Geophys. Geosyst.,
% doi:10.1002/2017GC006884


function varargout = SedCTimage(varargin)
% SedCTimage MATLAB code for SedCTimage.fig
%      SedCTimage, by itself, creates a new SedCTimage or raises the existing
%      singleton*.
%
%      H = SedCTimage returns the handle to a new SedCTimage or the handle to
%      the existing singleton*.
%
%      SedCTimage('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in SedCTimage.M with the given input arguments.
%
%      SedCTimage('Property','Value',...) creates a new SedCTimage or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before SedCTimage_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to SedCTimage_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help SedCTimage

% Last Modified by GUIDE v2.5 04-Jan-2017 11:45:26

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @SedCTimage_OpeningFcn, ...
                   'gui_OutputFcn',  @SedCTimage_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before SedCTimage is made visible.
function SedCTimage_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no outputgs args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to SedCTimage (see VARARGIN)

% Choose default command line outputgs for SedCTimage
handles.outputgs = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes SedCTimage wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = SedCTimage_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning outputgs args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line outputgs from handles structure
varargout{1} = handles.outputgs;


%-----------------------------------

% Open files
function open_folder_Callback(hObject, eventdata, handles)
Input = uigetdir('*.dpro.tiff', 'Select Directory with SedCT Output');
if isnan(Input)
    set(hObject, 'String', NaN);
    errordlg('Select an input DICOM folder','Error');
end

handles.image.files = Input;
guidata(hObject,handles);
Filebox_Callback(hObject, eventdata, handles);
function Filebox_Callback(hObject, eventdata, handles)
d = dir([handles.image.files, '/*.dpro.tiff']);
set(handles.Filebox, 'string', {d.name});
function Filebox_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%Process Pannel
function Process_Callback(hObject, eventdata, handles)
d = dir([handles.image.files, '/*.dpro.tiff']);
for n = 1:length(d)
    image(n).ct = imread([handles.image.files, '/', d(n).name]);
%     image(n).ct = log(double(imread([handles.image.files, '/', d(n).name])));
end

x = [];
for n = 1:length(d)
    x = [x; image(n).ct(:)];
end
x = double(x);
i = x <= 0;
x(i) = NaN;

mn = mean(x, 'omitnan');

st = std(x, 'omitnan');

set(handles.UpStdbox, 'Value', round(mn + st), 'String', round(mn + st));
if mn - st < 0
    bbb = 0;
else bbb = mn - st;
end
set(handles.dwnstdbox, 'Value', round(bbb), 'String', round(bbb));

urange = str2num(get(handles.UpStdbox, 'String'));
lrange = str2num(get(handles.dwnstdbox, 'String'));

num = length(d);

set(handles.text2, 'String', ['Mean: ' num2str(mn)])
set(handles.text3, 'String', ['St. Dev.: ' num2str(st)])
handles.image.dir = d;
handles.image.mean = mn;
handles.image.std = st;
handles.image.n = n;
handles.image.urange = urange;
handles.image.lrange = lrange;
handles.image.image = image;

if get(handles.radiobutton1, 'Value') == 1
    fc = 0;
else fc = 1;
end
handles.image.fc = fc;

set(handles.RangeText, 'String', ['Range: '... 
    num2str(lrange) ' - '... 
    num2str(urange)]);
implot(image, num, mn, st, lrange, urange, fc, handles)
guidata(hObject,handles);


function implot(images, num, mn, st, l, u, fc, handles)
for n = 1:length(images)
    x = double(images(n).ct);
%     i = x == 0;
%     x(i) = NaN;
%     x = x - st * l;
%     x = x/(st * u);
%     i = x < 0;
%     x(i) = 0;
%     i = x > 1;
%     x(i) = 1;
    result(n).ct = x;
end


for n = 1:num
    subplot(1, num+2, n+1);
    imshow(result(n).ct);
    caxis([l u])
    if fc ==1
        colormap('Jet')
    else colormap('Gray')
    end
end
    subplot(1, num+2, num+2)
    colorbar
%     chigh = (round(handles.image.mean + handles.image.urange*handles.image.std));
%     clow = (round(handles.image.mean - handles.image.lrange*handles.image.std));
    caxis([l u])
    axis off
handles.image.image = result;


% function Meanbox_Callback(hObject, eventdata, handles)
% function Meanbox_CreateFcn(hObject, eventdata, handles)
% % hObject    handle to Meanbox (see GCBO)
% % eventdata  reserved - to be defined in a future version of MATLAB
% % handles    empty - handles not created until after all CreateFcns called
% 
% % Hint: edit controls usually have a white background on Windows.
% %       See ISPC and COMPUTER.
% if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
%     set(hObject,'BackgroundColor','white');
% end
% function Mean_Callback(hObject, eventdata, handles)
% image = handles.image.image;
% num = handles.image.n;
% mn = str2num(get(handles.Meanbox, 'String'));
% handles.image.mean = mn;
% st = handles.image.std;
% lrange = handles.image.lrange;
% urange = handles.image.urange;
% 
% set(handles.RangeText, 'String', ['Range: '... 
%     num2str(round(handles.image.mean - handles.image.lrange*handles.image.std)) ' - '... 
%     num2str(round(handles.image.mean + handles.image.urange*handles.image.std))]);
% implot(image, num, mn, st, lrange, urange, handles.image.fc, handles)
% guidata(hObject, handles);

function UpStdbox_Callback(hObject, eventdata, handles)
function UpStdbox_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function urange_Callback(hObject, eventdata, handles)
image = handles.image.image;
num = handles.image.n;
mn = handles.image.mean;
st = handles.image.std;
lrange = handles.image.lrange;
urange = str2num(get(handles.UpStdbox, 'String'));
handles.image.urange = urange;

set(handles.RangeText, 'String', ['Range: '... 
    num2str(lrange) ' - '... 
    num2str(urange)]);
implot(image, num, mn, st, lrange, urange, handles.image.fc, handles)
guidata(hObject, handles);

function dwnstdbox_Callback(hObject, eventdata, handles)
function dwnstdbox_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function lrange_Callback(hObject, eventdata, handles)
image = handles.image.image;
num = handles.image.n;
mn = handles.image.mean;
handles.image.mean = mn;
st = handles.image.std;
lrange = str2num(get(handles.dwnstdbox, 'String'));
handles.image.lrange = lrange;
urange = handles.image.urange;

set(handles.RangeText, 'String',...
    ['Range: '... 
    num2str(lrange) ' - ' ...
    num2str(urange)]);
implot(image, num, mn, st, lrange, urange, handles.image.fc, handles)
guidata(hObject, handles);

function RangeText_Callback(hObject, eventdata, handles)
function RangeText_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% output the gray scale image
function outputgs_Callback(hObject, eventdata, handles)
image = handles.image.image;
urange = handles.image.urange;
lrange = handles.image.lrange;
st = handles.image.std;
PathName = handles.image.files;
d = handles.image.dir;

for n = 1:length(image)
    x = double(image(n).ct);
    i = x == 0;
    x(i) = NaN;
    x = x - lrange;
    x = x/(urange - lrange);
    i = x < 0;
    x(i) = 0;
    i = x > 1;
    x(i) = 1;
    x = x*255 + 1;
    i = x == 0;
    x(i) = 1;
    i = isnan(x);
    x(i) = 0;
    
        if get(handles.Scale, 'Value') == 1
            [l1 l2] = size(x);
            t = zeros(l1, 50);
            for w = [1:40:l1]
                t(w, 1:25) = ones(1, 25)*255;
            end
            for w = [2:40:l1]
                t(w, 1:25) = ones(1, 25)*255;
            end
            for w = [40:40:l1]
                t(w, 1:25) = ones(1, 25)*255;
            end
            for w = [1:200:l1]
                t(w, 1:50) = ones(1, 50)*255;
            end
            for w = [2:200:l1]
                t(w, 1:50) = ones(1, 50)*255;
            end
            for w = [200:200:l1]
                t(w, 1:50) = ones(1, 50)*255;
            end
            x = [t, x];
        end

    filename = strread(d(n).name, '%s', 'delimiter', '.');
    FileName = [filename(1)];
    
    imwrite(x, gray(256), [PathName '/' FileName{:} '_'...
        num2str(lrange) '-'...
    num2str(urange)...
    '_gs.png'], 'png');
end
% temp = figure(2);
% colormap(gray)
% c = colorbar;
% caxis([0 1]) 
% axis off
% imwrite(frame2im(getframe(c)), [PathName '/'...
%         num2str(lrange) '-'...
%     num2str(urange)...
%     '_gs.png'], 'png');
% close(temp)

% Output the false color image
function outputfc_Callback(hObject, eventdata, handles)
image = handles.image.image;
urange = handles.image.urange;
lrange = handles.image.lrange;
st = handles.image.std;
PathName = handles.image.files;
d = handles.image.dir;

for n = 1:length(image)
    x = double(image(n).ct);
    i = x == 0;
    x(i) = NaN;
    x = x - lrange;
    x = x/(urange - lrange);
    i = x < 0;
    x(i) = 0;
    i = x > 1;
    x(i) = 1;
    x = x*255 + 1;
    i = x == 0;
    x(i) = 1;
    i = isnan(x);
    x(i) = 0;
    
    
    if get(handles.Scale, 'Value') == 1
        [l1 l2] = size(x);
        t = zeros(l1, 50);
        for w = [1:40:l1]
            t(w, 1:25) = ones(1, 25)*255;
        end
        for w = [2:40:l1]
            t(w, 1:25) = ones(1, 25)*255;
        end
        for w = [40:40:l1]
            t(w, 1:25) = ones(1, 25)*255;
        end
        for w = [1:200:l1]
            t(w, 1:50) = ones(1, 50)*255;
        end
        for w = [2:200:l1]
            t(w, 1:50) = ones(1, 50)*255;
        end
        for w = [200:200:l1]
            t(w, 1:50) = ones(1, 50)*255;
        end
        x = [t, x];
    end

    filename = strread(d(n).name, '%s', 'delimiter', '.');
    FileName = [filename(1)];
    
    imwrite(x, jet(256), [PathName '/' FileName{:} '_'...
        num2str(lrange) '-'...
    num2str(urange)...
    '_fc.png'], 'png');
    
end
% temp = figure(2);
% colormap(jet)
% c = colorbar;
% caxis([0 1]) 
% axis off
% imwrite(frame2im(getframe(c)), [PathName '/'...
%         num2str(lrange) '-'...
%     num2str(urange)...
%     '_fc.png'], 'png');
% close(temp)

%Color Scale
function RadioSelect(hObject, eventdata, handles)
set(handles.radiobutton1, 'Value', get(handles.radiobutton1, 'Min'));
set(handles.radiobutton2, 'Value', get(handles.radiobutton2, 'Min'));
function radiobutton1_Callback(hObject, eventdata, handles)
RadioSelect(hObject, eventdata, handles)
set(handles.radiobutton1, 'Value', 1)
image = handles.image.image;
num = handles.image.n;
mn = handles.image.mean;
handles.image.mean = mn;
st = handles.image.std;
lrange = handles.image.lrange;
urange = handles.image.urange;
handles.image.fc = 0;

implot(image, num, mn, st, lrange, urange, handles.image.fc, handles)
guidata(hObject, handles);
function radiobutton2_Callback(hObject, eventdata, handles)
RadioSelect(hObject, eventdata, handles)
set(handles.radiobutton2, 'Value', 1)
image = handles.image.image;
num = handles.image.n;
mn = handles.image.mean;
handles.image.mean = mn;
st = handles.image.std;
lrange = handles.image.lrange;
urange = handles.image.urange;
handles.image.fc = 1;

implot(image, num, mn, st, lrange, urange, handles.image.fc, handles)
guidata(hObject, handles);


% Check box to include scale marks
function Scale_Callback(hObject, eventdata, handles)
