% Ref: Bertram et al., Am J Physiol Endocrinol Metab, 301: E742-E747, 2011.

% This Matlab code calculates a synchronization index quantifying the
% degree of synchronization between two or more islets. It was used to
% calculate the synchronization indices in 
% X. Zhang, A. Daou, T. M. Truong, R. Bertram, and M. G. Roper
% "Synchronization of mouse islets of Langerhans by glucose waveforms"
% American Journal of Physiology - Endocrinology and Metabolism 
% 301: E742?E747, 2011.

% This software is run by starting MATLAB, Running the "GUI.m" file. 
% Both files "GUI.fig" and "GUI.m" should be in the same directory.

% All islets to be simulated should be text files containing ONLY two
% columns of data. The first column is the time data points, and the second
% column contains the calcium concentration data points. Any other data
% included in the text file interferes with the algorithm and will not lead
% to correct results.   

% Moreover, all islet files should be named in the form "islet_xy"
% where xy represents the number of the islet. For instance, "islet_01" &
% "islet_12" to represent islets 1 and 12 respectively, and so on. If the
% islet number is less than 10, two digits must be used.
% For instance, islet number 2 should be named "islet_02" and NOT "islet_2".

% Using the "Select" button, the user selects the islets to be simulated
% for synchrony. Here, multiple islet selection is enabled for efficiency.
% By pressing on the "Open" button from the file chooser dialog box, the
% selected islets' file paths will be listed in the text area just beneath
% the "Select" button. 

% In the "Master Islet Number" text field, the user enters the number of
% the islet that is to be compared for synchrony with the rest of the
% islets. The default islet number is 1. The master islet number must be a
% number that belongs to the list of entered islets. For instance, if the
% selected islets by the user were "islet_02", "islet_03" and "islet_05",
% then entering a value of 1 in the master islet textfield will lead to a
% running error because islet number 1 does not belong to the list of
% selected islets.

% The "Number of Bins" textfield specify indirectly the accuracy of
% calculation. The larger this integer is, the more accurate the
% synchronization score is. However, for large scores, numerical errors
% might show up and some of the scores might appear as "NAN". If that
% happens, one should lower the number of bins until the "NAN" disappears.
% The default number of bins is 10. 

% In the "Start Time" and "End Time" text fields, the user enters the start
% time and end time of simulation that the algorithm uses to synchronize
% the selected islets. Both start and end times should be times that
% occurs within the time trace of the islets. Moreover, all islets should
% have the SAME time trace, and thus the same number of data points.

% Once the islets are selected and their paths are listed in the menu,
% one can press on any of the islets in the list and then press on the
% "View Selected Islet" button. This will open a figure that contains the
% trace of that particular islet (time vs. calcium concentration). It's
% important to note here that this option requires entering start and end
% times. In this case, the trace will show the calcium concentration only
% during that time interval specified by the start and end times.

% Instead of viewing a particular islet, the user has the option to
% superimpose ALL selected islets together. This is done by pressing on
% "SuperImpose All Islets".

% Morever, the user has the option to superimpose a particular set of
% selected islets. This is done by entering the islet numbers in the text
% field separated by commas, and then pressing on "Superimpose Entered
% Islets". All entered islets' numbers must belong to the list of
% selected islets. 

% The user can also open the glucose profile by pressing on "Open Glucose
% Profile" button and selecting the file containing the data points for the
% glucose profile.

% Once the islets are selected, the master islet number, the number of bins
% and the start and end times are all entered, then the user can press on
% the "Synchronize" button for generating the average synchronization index. 

% Basically, a synchronization index (SI) is generated for every islet
% compared with the master islet. An average of all these synchronization
% Indices is then generated. This average synchronization index
% (ASI) is listed in the text area titled "Average Synchronization Index
% (ASI)". Pressing on "View Details" button will list under it the
% synchronization index of every two islets simulated. 

% In addition, the software runs every islet against all others. In other
% words, even though a master islet is entered and its ASI is calculated,
% the software then takes every islet as a master islet and runs it against
% all the other islets. The results of this simulation are shown in the bar
% chart on the right bottom corner of the panel. The bar chart shows the
% islet number VS the Average Synchronization Index, where the islet number
% represents the islet that had been simulated as a master islet and the
% value of the bar at this islet represents the ASI generated. Then, an
% average of all these averages is calculated and plotted on the bar chart
% as a blue horizontal line and its value is listed in the title of the bar
% chart. 


function varargout = GUI(varargin)

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GUI_OpeningFcn, ...
                   'gui_OutputFcn',  @GUI_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


function Select_Callback(hObject, eventdata, handles)
% hObject    handle to Select (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[filesNames, filesPath, filterIndex] = uigetfile('*.txt', 'Pick a file', 'MultiSelect', 'on');

if(filterIndex ~= 0) % if the user didn't press cancel or opened NO files
    % if the user selects more than one file: Apparently, if the user
    % selects 5 items, then the return filesNames is a 1 by 5 CELL array,
    % but if the user selects one item, then the return filesNames is a 1
    % by N array where N is the size of the string of the returned file.
    % For example, if the selected file name is arij.txt, that's a size of
    % 8, so the return filesNames has a 1 by 8 size!
    % So the method ischar makes sure that the returned filesNames is not a
    % single string, otherwise the for loop doesn't work.
    if(ischar(filesNames)~=1)         
        for i=1:size(filesNames,2)
            filesNames(i) = strcat(filesPath,filesNames(i));
        end
    else
        filesNames = strcat(filesPath,filesNames);
    end
    
    set(handles.ListOfFiles,'String',filesNames,...
            'Value',1)
    guidata(hObject, handles);
    
end

function synchronize_Callback(hObject, eventdata, handles)
% hObject    handle to synchronize (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

filesNames = get(handles.ListOfFiles,'String');

% if the number of selected files was bigger than zero
if(size(filesNames,2)~=0) 
    % if the number of selected files is bigger than one: 
    % ischar function check whether filesNames is a string of characters or
    % not, if yes that means one item had been selected, if not that means
    % it is a cell array and thus we will be comparing more than one item
    % for synchrony
    if(ischar(filesNames)~=1) 
        nBinsText = get(handles.nBinsTF, 'String');        
        nBins = str2double(nBinsText);
        
        % sort islet names and numbers in ascending order
        filesNames = sort(filesNames);

        if(isnan(nBins)~=1)
            masterIsletText = get(handles.masterIsletTF, 'String');  
            masterIsletNumber = str2num(masterIsletText);
            
            if(isnan(masterIsletNumber)~=1)
                % if the user entered a decimal by mistake, round it
                masterIsletNumber = round(masterIsletNumber); 
                
                startTimeText = get(handles.startTimeTF, 'String');  
                endTimeText = get(handles.endTimeTF, 'String');  
                
                startTime = str2double(startTimeText);
                endTime = str2double(endTimeText);
                
                if(isnan(startTime)~=1 || isnan(endTime)~=1)
                    numberOfIslets = size(filesNames,1);
                    % HERE WE GO       
                    AllIslets = cell(1,numberOfIslets);
                            
                    % save all the islets in the cell array. The
                    % usage of char(filesNames(i)) is because it
                    % seems that filesNames(i) is not a string and
                    % that's why it needs to be casted.
                    for i=1:numberOfIslets
                        fid = fopen(char(filesNames(i)),'r');
                        AllIslets{i} = fscanf(fid,'%f',[2, inf]);
                        fclose(fid);
                    end 
                    
                    % Get the islet numbers by extracting the
                    % substrings. For example, if the path of the
                    % islet name is
                    % C:\Users\KeenEye\Documents\MATLAB\Synchroniza
                    % tion\islet_04.txt
                    % then this piece of code down extracts 04 from
                    % it and save it as a number
                    isletNumbers = zeros(1,numberOfIslets);
                    for i=1:numberOfIslets
                        isletNumberStrings = char(filesNames(i));
                        isletNumberStrings = isletNumberStrings(length(char(filesNames(i)))-5:...
                           length(char(filesNames(i)))-4);
                        isletNumbers(i) = str2num(isletNumberStrings);
                    end
                            
                    % Now test if the master islet belongs to the
                    % selected islets
                    belong=0;
                    for i=1:numberOfIslets
                        if(isletNumbers(i)==masterIsletNumber)
                            belong = 1;
                            break;
                        end
                    end                            
                    if(belong==1)
                        if(startTime < endTime)                            
%                             numberOfIntervalsText = get(handles.numberOfIntervalsTF, 'String');
%                             numberOfIntervals = str2num(numberOfIntervalsText);
                            
                            numberOfIntervals = 1;
                            if(isnan(numberOfIntervals)~=1)
                                if(numberOfIntervals>0)
                                    index = getIndexOfIslet(masterIsletNumber, isletNumbers);
                                    masterIslet = AllIslets{index};
                                    masterIslet = masterIslet';

                                    time = masterIslet(:,1);
                                    calciumMaster = masterIslet(:,2);
                                    
                                    startIndex = getTimeIndexFromTime(startTime, time);
                                    endIndex = getTimeIndexFromTime(endTime, time);

                                    if(startIndex == -1 || endIndex == -1)
                                                msgbox('Error in entring the START or END time! Time can not be negative and START and END time should be within the islet time range', ...
                                                    'Again, inappropriate entry!');
                                    else
                                        [startIndices, endIndices] = getTimeIndicesFromTimeAndInterval(startTime, endTime, time, numberOfIntervals);
                                        
                                        individualsynchIndicesStrings = cell(numberOfIntervals,numberOfIslets);
                                        averageSynchIndicesStrings = cell(1, numberOfIntervals);

                                        allIndicesArij = [];
                                        for j=1:numberOfIntervals                                            
                                            averageSynchIndex(j) = 0;
                                                                                        
                                            for k=1:(numberOfIslets)
                                                currentIsletNumber = isletNumbers(k);
                                                if(currentIsletNumber ~= masterIsletNumber)
                                                    currentIslet = AllIslets{k};
                                                    currentIslet = currentIslet';

                                                    calciumCurrent = currentIslet(:,2);

                                                    synchIndex = getSynchIndex(calciumMaster(startIndices(j):endIndices(j)), ...
                                                        calciumCurrent(startIndices(j):endIndices(j)), nBins);
                                                    
                                                    allIndicesArij = [allIndicesArij, synchIndex];
                                                    
                                                    individualsynchIndicesStrings{j,k} = strcat('SI for Islet', 32, num2str(masterIsletNumber), 32, ...
                                                            'and Islet', 32, num2str(currentIsletNumber), 32, '=', 32, num2str(synchIndex));
                                                    
                                                    averageSynchIndex(j) = averageSynchIndex(j) + synchIndex;
                                                end
                                            end    
                                            
                                            xlswrite('02_24_1006_6TO16.xlsx', allIndicesArij, 1, 'B21');
                                            
                                            averageSynchIndex(j) = averageSynchIndex(j)/(numberOfIslets-1);
                                            
                                            if(isnan(averageSynchIndex)~=1)
                                                averageSynchIndicesStrings{j} = strcat('ASI between', 32, num2str(time(startIndices(j))), 32, ...
                                                        'min and', 32, num2str(time(endIndices(j))), 32, 'min =', 32, num2str(averageSynchIndex(j)));
                                            else
                                                averageSynchIndicesStrings{j} = strcat('ASI between ', num2str(time(startIndices(j))), ...
                                                        'min and', num2str(time(endIndices(j))), 'min = -1 (nbins wrong!)');
                                            end                                                                                        
                                        end
                                        
                                        set(handles.averageSynchIndicesList,'String',averageSynchIndicesStrings,...
                                                    'Value',1);
                                        guidata(hObject, handles);
                                        
                                        set(handles.individualSynchIndicesList,'String',{},...
                                                    'Value',1);
                                                
                                        getBarChartData(AllIslets, isletNumbers, numberOfIslets, ...
                                            startIndex, endIndex, nBins, handles, hObject);
                                        
                                    end
                                else
                                    msgbox('Enter an appropriate number for intervals! It must be positive!', ...
                                    'Error in data entry!');  
                                end                                
                            else
                                msgbox('Enter the number for intervals!', ...
                                'Missing data entry!');                                
                            end
                        else
                            msgbox('How can the start time be larger than end time???', ...
                                'Again, inappropriate entry!');
                        end
                    else
                        msgbox('Master Islet does not belong to the selected islets!', ...
                                'Again, inappropriate entry!'); 
                    end
                else
                    msgbox('Enter an appropriate numeric value in the START and END time textfields!', ...
                        'Non-numeric values entered!');
                end
            else
                msgbox('Enter an appropriate numeric value in the MASTER islet number textfield!',...
                'Non-numeric values entered!');
            end           
        else
            msgbox('Enter an appropriate numeric value in the NUMBER OF BINS textfield!',...
                'Non-numeric values entered!');
        end
    else
        msgbox('The number of selected islet files does not make sense! Select at least TWO islet files to test for synchrony!', ...
            'Dude, not right!');
    end
else
    msgbox('Select first at least two islet files to test for synchrony!',...
        'Dude, Select Something!');
end

function [individualsynchIndicesStrings] = synchronizeAgain(hObject, eventdata, handles)

filesNames = get(handles.ListOfFiles,'String');

% if the number of selected files was bigger than zero
if(size(filesNames,2)~=0) 
    % if the number of selected files is bigger than one: 
    % ischar function check whether filesNames is a string of characters or
    % not, if yes that means one item had been selected, if not that means
    % it is a cell array and thus we will be comparing more than one item
    % for synchrony
    if(ischar(filesNames)~=1) 
        nBinsText = get(handles.nBinsTF, 'String');        
        nBins = str2double(nBinsText);
        
        % sort islet names and numbers in ascending order
        filesNames = sort(filesNames);

        if(isnan(nBins)~=1)
            masterIsletText = get(handles.masterIsletTF, 'String');  
            masterIsletNumber = str2num(masterIsletText);
            
            if(isnan(masterIsletNumber)~=1)
                % if the user entered a decimal by mistake, round it
                masterIsletNumber = round(masterIsletNumber); 
                
                startTimeText = get(handles.startTimeTF, 'String');  
                endTimeText = get(handles.endTimeTF, 'String');  
                
                startTime = str2double(startTimeText);
                endTime = str2double(endTimeText);
                
                if(isnan(startTime)~=1 || isnan(endTime)~=1)
                    numberOfIslets = size(filesNames,1);
                    % HERE WE GO       
                    AllIslets = cell(1,numberOfIslets);
                            
                    % save all the islets in the cell array. The
                    % usage of char(filesNames(i)) is because it
                    % seems that filesNames(i) is not a string and
                    % that's why it needs to be casted.
                    for i=1:numberOfIslets
                        fid = fopen(char(filesNames(i)),'r');
                        AllIslets{i} = fscanf(fid,'%f',[2, inf]);
                        fclose(fid);
                    end 
                    
                    % Get the islet numbers by extracting the
                    % substrings. For example, if the path of the
                    % islet name is
                    % C:\Users\KeenEye\Documents\MATLAB\Synchroniza
                    % tion\islet_04.txt
                    % then this piece of code down extracts 04 from
                    % it and save it as a number
                    isletNumbers = zeros(1,numberOfIslets);
                    for i=1:numberOfIslets
                        isletNumberStrings = char(filesNames(i));
                        isletNumberStrings = isletNumberStrings(length(char(filesNames(i)))-5:...
                           length(char(filesNames(i)))-4);
                        isletNumbers(i) = str2num(isletNumberStrings);
                    end
                            
                    % Now test if the master islet belongs to the
                    % selected islets
                    belong=0;
                    for i=1:numberOfIslets
                        if(isletNumbers(i)==masterIsletNumber)
                            belong = 1;
                            break;
                        end
                    end                            
                    if(belong==1)
                        if(startTime < endTime)                            
%                             numberOfIntervalsText = get(handles.numberOfIntervalsTF, 'String');
%                             numberOfIntervals = str2num(numberOfIntervalsText);
                            numberOfIntervals=1;
                            if(isnan(numberOfIntervals)~=1)
                                if(numberOfIntervals>0)
                                    index = getIndexOfIslet(masterIsletNumber, isletNumbers);
                                    masterIslet = AllIslets{index};
                                    masterIslet = masterIslet';

                                    time = masterIslet(:,1);
                                    calciumMaster = masterIslet(:,2);
                                    
                                    startIndex = getTimeIndexFromTime(startTime, time);
                                    endIndex = getTimeIndexFromTime(endTime, time);

                                    if(startIndex == -1 || endIndex == -1)
                                                msgbox('Error in entring the START or END time! Time can not be negative and START and END time should be within the islet time range', ...
                                                    'Again, inappropriate entry!');
                                    else
                                        [startIndices, endIndices] = getTimeIndicesFromTimeAndInterval(startTime, endTime, time, numberOfIntervals);
                                        
                                        individualsynchIndicesStrings = cell(numberOfIntervals,numberOfIslets);
                                        averageSynchIndicesStrings = cell(1, numberOfIntervals);

                                        for j=1:numberOfIntervals                                            
                                            averageSynchIndex(j) = 0;
                                                                                        
                                            for k=1:(numberOfIslets)
                                                currentIsletNumber = isletNumbers(k);
                                                if(currentIsletNumber ~= masterIsletNumber)
                                                    currentIslet = AllIslets{k};
                                                    currentIslet = currentIslet';

                                                    calciumCurrent = currentIslet(:,2);

                                                    synchIndex = getSynchIndex(calciumMaster(startIndices(j):endIndices(j)), ...
                                                        calciumCurrent(startIndices(j):endIndices(j)), nBins);
                                                    
%                                                     sprintf('%f', synchIndex);
                                                    
                                                    individualsynchIndicesStrings{j,k} = strcat('SI for Islet', 32, num2str(masterIsletNumber), 32, ...
                                                            'and Islet', 32, num2str(currentIsletNumber), 32, '=', 32, num2str(synchIndex));
                                                    
                                                    averageSynchIndex(j) = averageSynchIndex(j) + synchIndex;
                                                else
                                                    individualsynchIndicesStrings{j,k} = '';
                                                end
                                            end    
                                            
                                            averageSynchIndex(j) = averageSynchIndex(j)/(numberOfIslets-1);
                                            
                                            if(isnan(averageSynchIndex)~=1)
                                                averageSynchIndicesStrings{j} = strcat('ASI between', 32, num2str(time(startIndices(j))), 32, ...
                                                        'min and', 32, num2str(time(endIndices(j))), 32, 'min =', 32, num2str(averageSynchIndex(j)));
                                            else
                                                averageSynchIndicesStrings{j} = strcat('ASI between ', num2str(time(startIndices(j))), ...
                                                        'min and', num2str(time(endIndices(j))), 'min = -1 (nbins wrong!)');
                                            end                                                                                        
                                        end
                                        
                                        set(handles.averageSynchIndicesList,'String',averageSynchIndicesStrings,...
                                                    'Value',1);
                                        guidata(hObject, handles);
                                        
                                        set(handles.individualSynchIndicesList,'String',{},...
                                                    'Value',1);
                                    end
                                else
                                    msgbox('Enter an appropriate number for intervals! It must be positive!', ...
                                    'Error in data entry!');  
                                end                                
                            else
                                msgbox('Enter the number for intervals!', ...
                                'Missing data entry!');                                
                            end
                        else
                            msgbox('How can the start time be larger than end time???', ...
                                'Again, inappropriate entry!');
                        end
                    else
                        msgbox('Master Islet does not belong to the selected islets!', ...
                                'Again, inappropriate entry!'); 
                    end
                else
                    msgbox('Enter an appropriate numeric value in the START and END time textfields!', ...
                        'Non-numeric values entered!');
                end
            else
                msgbox('Enter an appropriate numeric value in the MASTER islet number textfield!',...
                'Non-numeric values entered!');
            end           
        else
            msgbox('Enter an appropriate numeric value in the NUMBER OF BINS textfield!',...
                'Non-numeric values entered!');
        end
    else
        msgbox('The number of selected islet files does not make sense! Select at least TWO islet files to test for synchrony!', ...
            'Dude, not right!');
    end
else
    msgbox('Select first at least two islet files to test for synchrony!',...
        'Dude, Select Something!');
end

function getBarChartData(AllIslets, isletNumbers, numberOfIslets, startIndex, endIndex, nBins, handles, hObject)

averageSynchIndices = zeros(1,numberOfIslets);
for i=1:numberOfIslets
    currentMasterIslet = AllIslets{i};
    currentMasterIslet = currentMasterIslet';

    calciumMaster = currentMasterIslet(:,2);
    
    averageSynchIndices(i) = 0;
    
    for k=1:(numberOfIslets)
        currentIsletNumber = isletNumbers(k);        
        if(k ~= i)
            currentIslet = AllIslets{k};
            currentIslet = currentIslet';

            calciumCurrent = currentIslet(:,2);
            synchIndex = getSynchIndex(calciumMaster(startIndex:endIndex), ...
                calciumCurrent(startIndex:endIndex), nBins);                                                    
                                                    
            averageSynchIndices(i) = averageSynchIndices(i) + synchIndex;
         end
     end    
     
     averageSynchIndices(i) = averageSynchIndices(i)/(numberOfIslets-1);
end

% averageSynchIndices
% aa=0;
% for j=1:size(averageSynchIndices,2)
%     aa = aa + averageSynchIndices(i);
% end
% 
% aa/numberOfIslets;

average = mean(averageSynchIndices);

colors = ['r','b','k','c','g','m'];

h=bar(handles.barGraph, isletNumbers(1), averageSynchIndices(1));
colormap summer;
grid on;
axis tight;
h(1).FaceColor = colors(mod(1, 6) + 1);
h(1).EdgeColor = colors(floor(1/6) + 1);
h(1).LineWidth = 2;
set(gca, 'XTick', isletNumbers);
hold on;

for i = 2:numberOfIslets
    h=bar(handles.barGraph, isletNumbers(i), averageSynchIndices(i));
    h(1).FaceColor = colors(mod(i, 6) + 1);
    h(1).EdgeColor = colors(floor(i/6) + 1);
    h(1).LineWidth = 2;
end

line([0.5,isletNumbers(numberOfIslets)+0.5], [average, average], 'LineWidth',2);
xlabel('Islet Number');
ylabel('Average Synchronization Index');
title(strcat('Average of all ASIs = ', 32, num2str(average), 32, '(blue line)'));
hold off;
    


% Assign a new color to each bar. bar (and barh) creates a barseries 
% object which encapsulates a set of patch objects for the bars. The 
% patches have face-vertex syntax. First get a handle for the children, 
%  and then obtain the vertices for the bars and the vertex color data: 
% ch = get(h,'Children');
% fvd = get(ch,'Faces');
% fvcd = get(ch,'FaceVertexCData');
% 
% for i = 1:numberOfIslets
%     fvcd(fvd(i,:)) = i;
% end
% set(ch,'FaceVertexCData',fvcd)

guidata(hObject, handles);

function viewIslet_Callback(hObject, eventdata, handles)

filesNames = get(handles.ListOfFiles,'String');

% if the number of selected files was bigger than zero
if(size(filesNames,2)~=0) 
    index_selected = get(handles.ListOfFiles,'Value');
    file_list = get(handles.ListOfFiles,'String');
    % Item selected in list box
    fileName = file_list{index_selected};
    
    fid = fopen(fileName,'r');
    islet = fscanf(fid,'%f',[2, inf]);
    
    islet = islet';
                            
    time = islet(:,1);
    calcium = islet(:,2);
    
    isletNumbers = zeros(1,size(filesNames,1));
    for i=1:size(filesNames,1)
         isletNumberStrings = char(filesNames(i));
         isletNumberStrings = isletNumberStrings(length(char(filesNames(i)))-5:...
             length(char(filesNames(i)))-4);
         isletNumbers(i) = str2num(isletNumberStrings);
    end
    
    startTimeText = get(handles.startTimeTF, 'String');  
    endTimeText = get(handles.endTimeTF, 'String');  
                
    startTime = str2double(startTimeText);
    endTime = str2double(endTimeText);
                
    if(isnan(startTime)~=1 || isnan(endTime)~=1)
        
        startIndex = getTimeIndexFromTime(startTime, time);
        endIndex = getTimeIndexFromTime(endTime, time);
                                    
        if(startIndex == -1 || endIndex == -1)
            msgbox('Error in entring the START or END time! Time can not be negative and START and END time should be within the islet time range', ...
               'Again, inappropriate entry!');
        else
            figure();
            plot(time(startIndex:endIndex), calcium(startIndex:endIndex), 'b-');
            xlabel('Time (min)');
            ylabel('[Ca^{++}] (\muM)');
            title(strcat('Calcium Concentration for Islet', 32, num2str(isletNumbers(index_selected))));
            axis tight
            set(gca,'FontWeight','bold');
            set(gca, 'Box', 'off' );
            set(gca, 'FontSize', 20);
            yl = get(gca, 'ylabel');
            set(yl, 'FontWeight', 'bold') 
            set(yl, 'FontSize', 20);
            xl = get(gca, 'xlabel');
            set(xl, 'FontWeight', 'bold') 
            set(xl, 'FontSize', 20);
            t = get(gca, 'title');
            set(t, 'FontWeight', 'bold') 
            set(t, 'FontSize', 22);            
        end
    else
         msgbox('Enter an appropriate numeric value in the START and END time textfields!', ...
                        'Non-numeric values entered!');
    end                
    
else
    msgbox('There are no selected islets!',...
        'Dude, You gotta select something!');
end

function superImposeAllIslets_Callback(hObject, eventdata, handles)

colors=[0 0 0; 0 0 255; 0 255 0; 255 0 0; 0 51 51; 0 0 102; 102 102 255;
    204 153 255; 255 102 102; 255 255 102; 202 204 0; 51 51 0; 153 255 153;
    51 255 153; 102 102 0; 153 153 0; 204 0 204; 255 204 204; 102 102 102;
    0 255 255; 255 0 255; 51 153 255; 255 153 153; 255 255 0;
    0 0 0;  0 0 255; 0 255 0; 255 0 0; 0 51 51; 0 0 102; 102 102 255;
    204 153 255; 255 102 102; 255 255 102; 202 204 0; 51 51 0; 153 255 153;
    51 255 153; 102 102 0; 153 153 0; 204 0 204; 255 204 204; 102 102 102;
    0 255 255; 255 0 255; 51 153 255; 255 153 153; 255 255 0];

colors = colors./255;

filesNames = get(handles.ListOfFiles,'String');

% if the number of selected files was bigger than zero
if(size(filesNames,2)~=0) 
    filesNames = sort(filesNames);
    
    numberOfIslets = size(filesNames,1);
    AllIslets = cell(1,numberOfIslets);
            
    for i=1:numberOfIslets
        fid = fopen(char(filesNames(i)),'r');
        AllIslets{i} = fscanf(fid,'%f',[2, inf]);
        fclose(fid);
    end 
    
    islet = AllIslets{1};
    islet = islet';            
    time = islet(:,1);

    figure();
    for i=1:numberOfIslets
        islet = AllIslets{i};
        islet = islet';
                    
        calcium = islet(:,2);
        calcium = calcium';
                    
        plot(time, calcium, 'Color', colors(i,:));
        hold on;
    end
    xlabel('Time (min)');
    ylabel('[Ca^{++}] (\muM)');
    title('Calcium Concentration for all the selected Islets');
    axis tight;    
    set(gca,'FontWeight','bold');
    set(gca, 'Box', 'off' );
    set(gca, 'FontSize', 20);
    yl = get(gca, 'ylabel');
    set(yl, 'FontWeight', 'bold') 
    set(yl, 'FontSize', 20);
    xl = get(gca, 'xlabel');
    set(xl, 'FontWeight', 'bold') 
    set(xl, 'FontSize', 20);
    t = get(gca, 'title');
    set(t, 'FontWeight', 'bold') 
    set(t, 'FontSize', 22);            
else
    msgbox('There are no selected islets!',...
        'Dude, You gotta select something!');
end

function superImposeEnteredIslets_Callback(hObject, eventdata, handles)
% hObject    handle to superImposeEnteredIslets (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

colors=[0 0 0; 0 0 255; 0 255 0; 255 0 0; 0 51 51; 0 0 102; 102 102 255;
                204 153 255; 255 102 102; 255 255 102; 202 204 0; 51 51 0; 153 255 153;
                51 255 153; 102 102 0; 153 153 0; 204 0 204; 255 204 204; 102 102 102;
                0 255 255; 255 0 255; 51 153 255; 255 153 153; 255 255 0;
                0 0 0;  0 0 255; 0 255 0; 255 0 0; 0 51 51; 0 0 102; 102 102 255;
                204 153 255; 255 102 102; 255 255 102; 202 204 0; 51 51 0; 153 255 153;
                51 255 153; 102 102 0; 153 153 0; 204 0 204; 255 204 204; 102 102 102;
                0 255 255; 255 0 255; 51 153 255; 255 153 153; 255 255 0];

colors = colors./255;
            
enteredIsletsText = get(handles.enteredIsletsTF, 'String');        
% nBins = str2double(enteredIsletsText);
remain = enteredIsletsText;

index=1;
enteredNumbers=0;
enteredNumbers(1)=-1;

while true
    [token, remain] = strtok(remain, ',');
    if isempty(token)
        break; 
    else
        number = str2double(token);
        if(isnan(number)~=1)
            enteredNumbers(index) = number;
            index = index+1;
        else
            msgbox('Enter appropriate numbers seperated by commas!',...
                'Error in Data Entry');
        end
    end    
end

if(enteredNumbers(1)~=-1)
    filesNames = get(handles.ListOfFiles,'String');
    filesNames = sort(filesNames);
    
    if(size(filesNames,2)~=0) 
        numberOfIslets = size(filesNames,1);
        AllIslets = cell(1,numberOfIslets);
        
        isletNumbers = zeros(1,numberOfIslets);
        for i=1:numberOfIslets
            isletNumberStrings = char(filesNames(i));
            isletNumberStrings = isletNumberStrings(length(char(filesNames(i)))-5:...
                length(char(filesNames(i)))-4);
            isletNumbers(i) = str2num(isletNumberStrings);
        end    
        
        allBelongs = 0;
        for k=1:size(enteredNumbers,2)
            for i=1:numberOfIslets
                if(isletNumbers(i)==enteredNumbers(k))
                    allBelongs = allBelongs + 1;
                    break;
                end
            end 
        end
        
        if(allBelongs==size(enteredNumbers,2))
            
            for i=1:numberOfIslets
                fid = fopen(char(filesNames(i)),'r');
                AllIslets{i} = fscanf(fid,'%f',[2, inf]);
                fclose(fid);
            end 
    
            islet = AllIslets{1};
            islet = islet';            
            time = islet(:,1);
    
            figure();
            enteredNumbers = sort(enteredNumbers);
            
            legends = cell(1,size(enteredNumbers,2));
            
            for i=1:size(enteredNumbers,2)
                index = getIndexOfIslet(enteredNumbers(i), isletNumbers);
                islet = AllIslets{index};
                islet = islet';

                calcium = islet(:,2);

                plot(time, calcium, 'Color', colors(i,:));
                hold on
                
                legends{i} = strcat('Islet', 32, num2str(enteredNumbers(i)));
            end   
            xlabel('Time (min)');
            ylabel('[Ca^{++}] (\muM)');
            title('Calcium Concentration for the entered Islets');
            axis tight;                
            legend(legends);
            set(gca,'FontWeight','bold');
            set(gca, 'Box', 'off' );
            set(gca, 'FontSize', 20);
            yl = get(gca, 'ylabel');
            set(yl, 'FontWeight', 'bold') 
            set(yl, 'FontSize', 20);
            xl = get(gca, 'xlabel');
            set(xl, 'FontWeight', 'bold') 
            set(xl, 'FontSize', 20);
            t = get(gca, 'title');
            set(t, 'FontWeight', 'bold') 
            set(t, 'FontSize', 22);            
        else
            msgbox('The islet numbers entered do not match with selected islets! Islet numbers entered should belong to the selected islet numbers!', 'Error in Data Entry');
        end
    else
        msgbox('No islets had been selected!',...
                'Select Islets First!');
    end
else
    msgbox('No numbers had been entered!',...
                'Error in Data Entry');
end

function glucose_Callback(hObject, eventdata, handles)
% hObject    handle to glucose (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[file_in, file_path] = uigetfile('*.txt','Open Glucose Profile TextFile');
file_name = [file_path file_in];

if(file_name)
    fid = fopen(file_name,'r');
    A = fscanf(fid,'%f',[2, inf]);
    fclose(fid);
    
    data = A';

    time = data(:,1);
    glucose = data(:,2);
    
    figure();
    plot(time, glucose, 'b-');
    xlabel('Time (min)');
    ylabel('Glucose Concentration (\muM)');
    title('Glucose Profile');
    axis tight;                
    set(gca,'FontWeight','bold');
    set(gca, 'Box', 'off' );
    set(gca, 'FontSize', 20);
    yl = get(gca, 'ylabel');
    set(yl, 'FontWeight', 'bold') 
    set(yl, 'FontSize', 20);
    xl = get(gca, 'xlabel');
    set(xl, 'FontWeight', 'bold') 
    set(xl, 'FontSize', 20);
    t = get(gca, 'title');
    set(t, 'FontWeight', 'bold') 
    set(t, 'FontSize', 22);      
end

function detailsButton_Callback(hObject, eventdata, handles)

listOfIndices = get(handles.averageSynchIndicesList,'String');

if(size(listOfIndices,2)~=0)
    index = get(handles.averageSynchIndicesList,'Value');
    individualsynchIndicesStrings = synchronizeAgain(hObject, eventdata, handles);
    
    j=1;
    for i=1:size(individualsynchIndicesStrings,2)
        if(strcmp(individualsynchIndicesStrings(i),'')~=1)
            strings(j) = individualsynchIndicesStrings(i);
            j = j+1;
        end
    end
    
%     set(handles.individualSynchIndicesList,'String',char(individualsynchIndicesStrings{index,:}),...
%                                                     'Value',1);
    set(handles.individualSynchIndicesList,'String',strings,...
                                                    'Value',1);
    set(handles.averageSynchIndicesList, 'Value',index);
    
    guidata(hObject, handles);
else
    msgbox('No Islets had been Synchronized!', 'Synchronize first!');
end



% --- Executes just before GUI is made visible.
function GUI_OpeningFcn(hObject, eventdata, handles, varargin)

% set(handles.nBinsTF, 'Userdata', [0 100 inf]);

% This function has no output 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 GUI (see VARARGIN)

% Choose default command line output for GUI
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% --- Outputs from this function are returned to the command line.
function varargout = GUI_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output 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 output from handles structure
varargout{1} = handles.output;

function nBinsTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function nBinsTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to nBinsTF (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 masterIsletTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function masterIsletTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to masterIsletTF (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 startTimeTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function startTimeTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to startTimeTF (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 endTimeTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function endTimeTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to endTimeTF (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
                   
% --- Executes on selection change in ListOfFiles.
function ListOfFiles_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function ListOfFiles_CreateFcn(hObject, eventdata, handles)
% hObject    handle to ListOfFiles (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox 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

% --- Executes on button press in Close.
function Close_Callback(hObject, eventdata, handles)

% --- Executes on selection change in averageSynchIndicesList.
function averageSynchIndicesList_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function averageSynchIndicesList_CreateFcn(hObject, eventdata, handles)
% hObject    handle to averageSynchIndicesList (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox 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 enteredIsletsTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function enteredIsletsTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to enteredIsletsTF (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 intervalSizeTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function intervalSizeTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to intervalSizeTF (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 numberOfIntervalsTF_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function numberOfIntervalsTF_CreateFcn(hObject, eventdata, handles)
% hObject    handle to numberOfIntervalsTF (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

% --- Executes on selection change in individualSynchIndicesList.
function individualSynchIndicesList_Callback(hObject, eventdata, handles)

% --- Executes during object creation, after setting all properties.
function individualSynchIndicesList_CreateFcn(hObject, eventdata, handles)
% hObject    handle to individualSynchIndicesList (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox 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 index = getIndexOfIslet(isletNumber, listOfIsletNumbers)

for i = 1:size(listOfIsletNumbers,2)
    if(isletNumber == listOfIsletNumbers(i))
        index = i;
        break;
    end
end

function synchIndex = getSynchIndex(ca1, ca2, nbins)

% Detrend the data
detrendedData1 = detrend(ca1);
detrendedData2 = detrend(ca2);

% Perform the Hilbert transform of the detrended data using Hilbert
% function.
hilbertDetrended1 = hilbert(detrendedData1);
hilbertDetrended2 = hilbert(detrendedData2);

% Calculate the instantaneous phase
instantPhase1 = unwrap(angle(hilbertDetrended1));
instantPhase2 = unwrap(angle(hilbertDetrended2));

% Calculate mod 2pi of the previously calculated phases
ca1_mod = mod(instantPhase1, 2*pi);
ca2_mod = mod(instantPhase2, 2*pi);

% Bin the phase of the first oscillator (data1), i.e., divide the interval
% [0,2pi] into N equal bins. The number of bins must be the same in all
% experiments to be compared, with no empty bin.

n = hist(ca1_mod, nbins);
[sorted_index idx] = sort(ca1_mod);
lambda = zeros(nbins,1);

counter = 0;
for k = 1:nbins
    for j = 1:n(k)
        counter = counter + 1;
        lambda(k) = lambda(k) + exp(1i*ca2_mod(idx(counter)));       
    end
    lambda(k) = lambda(k)/n(k);
end

synchIndex = sum(abs(lambda))/nbins;

function index = getTimeIndexFromTime(targetTime, timeArray)

index = -1;
if(targetTime<0)
    index = -1;
else
    for i=1:size(timeArray,1)
        if(timeArray(i)>=targetTime)
            index = i;
            break;
        end
    end
end

function [startIndices, endIndices] = getTimeIndicesFromTimeAndInterval(startTime, endTime, time, numberOfIntervals)


startIndex = getTimeIndexFromTime(startTime, time);
endIndex = getTimeIndexFromTime(endTime, time);

jump = round((endIndex - startIndex)/numberOfIntervals);

startIndices(1) = startIndex;
endIndices(1) = startIndex + jump;

for i = 2:numberOfIntervals
    if(endIndices(i-1) < endIndex)
        startIndices(i) = endIndices(i-1);
        endIndices(i) = startIndices(i) + jump;
        
        if(endIndices(i) > endIndex)
            endIndices(i) = endIndex;
        end
    end
end