function parafacresidual_gdp(parafacFac,tmp,ncomp,Ppmscale)
%% parafacresidual_gdp info(parafacFac,tmp,ncomp,Ppmscale);
%   parafacresidual_gdp.m: plots the residual components generated by parafac,
%   in an interactive graphical user interface
%
%   --------------------------------INPUT------------------------------------
%   parafacFac  =   Factors generated by parafac. Is a 3 element cell vector:
%                   Factors{1}=A, Factors{2}=B, Factors{3}=C
%   tmp         =   Original data set (used in parafac)
%   ncomp       =   Number of compents fitted for parafac
%   Ppmscale    =   Scale of the direct dimension (in ppm)
%
%
%   Example:
%
%   See also: dosy_mn, score_mn, decra_mn, mcr_mn, varianimport,
%             brukerimport, jeolimport, peakpick_mn, dosyplot_mn,
%             dosyresidual, dosyplot_gui, scoreplot_mn, decraplot_mn,
%             mcrplot_mn
%
%   This is a part of the GNAT
%   Copyright  2017  <Mathias Nilsson>%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You should have received a copy of the GNU General Public License along
%   with this program; if not, write to the Free Software Foundation, Inc.,
%   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
%   Dr. Mathias Nilsson
%   School of Chemistry, University of Manchester,
%   Oxford Road, Manchester M13 9PL, UK
%   Telephone: +44 (0) 161 306 4465
%   Fax: +44 (0)161 275 4598
%
%     Guilherme Dal Poggetto, PhD Student
%     Univeristy of Manchester, 2018
%     guilherme.dalpoggetto@manchester.ac.uk
%
%% Setup the GUI CONTROLS
parres3D.temp='';
[hs]=SetupGUI();
[hs]=SetupAxesPanel(hs);
[hs]=SetupPlotControlPanel(hs);
guidata(hs.parresgui,parres3D)
InitiateData()
Display_Callback()
set(hs.text,'String',['/' num2str(parres3D.ncomp)])
guidata(hs.parresgui,parres3D)
set(hs.parresgui,'Visible','on')
%% GUI functions
    function [handles]=SetupGUI()
        handles.parresgui=figure('Units','normalized',...
            'MenuBar','none',...
            'Name','PARAFAC residual Plot',...
            'NumberTitle','Off',...
            'Toolbar','Figure',...
            'OuterPosition',[0.1 0.25 0.6 0.65],...
            'Visible','off');
        
        %Clean up the Toolbar, removing things we don't need
        rmv = findall(handles.parresgui,'ToolTipString','New Figure');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Open File');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Link Plot');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Insert Legend');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Data Cursor');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Edit Plot');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Brush/Select Data');
        set(rmv,'Visible','Off')
        rmv = findall(handles.parresgui,'ToolTipString','Hide Plot Tools');
        set(rmv,'Visible','Off')
        
    end
    function [handles]=SetupAxesPanel(handles)
        handles.AxesPanel=uipanel(...
            'Parent',handles.parresgui,...
            'Units','normalized',...            %'BorderType','none',...
            'Position',[0.0 0.0 0.8 1],...
            'Visible','on');
        handles.Axes = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.02 0.96 0.96]);
        handles.Axes21 = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.01 0.96 0.48]);
        handles.Axes22 = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.5 0.96 0.48]);
        handles.Axes31 = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.01 0.96 0.32]);
        handles.Axes32 = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.34 0.96 0.32]);
        handles.Axes33 = axes(...
            'Parent',handles.AxesPanel,...
            'Units','normalized',...
            'Visible','off',...
            'Position',[0.02 0.67 0.96 0.32]);
    end
    function [handles]=SetupPlotControlPanel(handles)
        handles.ControlPanel=uipanel(...
            'Parent',handles.parresgui,...
            'Units','normalized',...
            'Position',[0.8 0.0 0.2 1],...
            'HitTest','off',...
            'Visible','on');
        %% --- Display mode control
        handles.ButtongroupDisplay=uibuttongroup(...
            'Parent',handles.ControlPanel,...
            'Units','Normalized',...
            'Title','Display mode',...
            'SelectionChangeFcn', {@Display_Callback},...
            'ForegroundColor','Blue',...
            'TitlePosition','CenterTop',...
            'FontWeight','Bold',...
            'Position',[0.005 0.8 0.99 0.2]);
        handles.RadioSum = uicontrol(...
            'Parent', handles.ButtongroupDisplay,...
            'Style','RadioButton',...
            'String','Sum (phase average)',...
            'TooltipString','Sum all spectra of selected concatenation dimension',...
            'Units','normalized',...
            'Position',[0.35 0.72 0.9 0.2]);
        handles.RadioRMS = uicontrol(...
            'Parent', handles.ButtongroupDisplay,...
            'Style','RadioButton',...
            'String','RMS',...
            'TooltipString','Root mean square spectra of selected concatenation dimension',...
            'Units','normalized',...
            'Position',[0.35 0.42 0.9 0.2]);
        handles.RadioFlip = uicontrol(...
            'Parent', handles.ButtongroupDisplay,...
            'Style','RadioButton',...
            'String','Flip',...
            'TooltipString','Permit to flip throught spectra of selected concatenation dimension',...
            'Units','normalized',...
            'Position',[0.35 0.12 0.9 0.2]);
        set(handles.ButtongroupDisplay,'SelectedObject',handles.RadioSum)
        %% --- Flipping control
        handles.FlipPanel=uipanel(...
            'Parent',handles.ControlPanel,...
            'Title','Spectrum',...
            'FontWeight','bold',...
            'TitlePosition','centertop',...
            'ForegroundColor','Blue',...
            'Units','Normalized',...
            'Position',[0.005 0.65 0.99 0.15]);
        handles.EditFlip=uicontrol(...
            'Parent',handles.FlipPanel,...
            'Style','edit',...
            'Units','Normalized',...
            'BackgroundColor','w',...
            'String',1,...
            'Enable','off',...
            'TooltipString','Current spectrum',...
            'Position',[0.28 0.15 0.25 0.7 ],...
            'CallBack', {@EditFlip_Callback});
        handles.text=uicontrol(...
            'Parent',handles.FlipPanel,...
            'Style','text',...
            'Units','Normalized',...
            'HorizontalAlignment','left',...
            'String','/ 1',...
            'Position',[0.59 -0.05 0.25 0.7 ]);
        handles.ButtonFlipMinus = uicontrol(...
            'Parent',handles.FlipPanel,...
            'Style','PushButton',...
            'String','-1',...
            'Enable','off',...
            'Units','normalized',...
            'TooltipString','Previous spectrum in the array',...
            'Position',[0.02 0.15 0.25 0.7],...
            'Callback',{@ButtonFlipMinus_Callback});
        handles.ButtonFlipPlus = uicontrol(...
            'Parent',handles.FlipPanel,...
            'Style','PushButton',...
            'String','+1',...
            'Units','normalized',...
            'Enable','off',...
            'TooltipString','Next spectrum in the array',...
            'Position',[0.75 0.15 0.25 0.7],...
            'Callback',{@ButtonFlipPlus_Callback});
        %% --- Concatenation dimension
        handles.ShowPanel=uipanel(...
            'Parent',handles.ControlPanel,...
            'Title','Showing',...
            'FontWeight','bold',...
            'TitlePosition','centertop',...
            'ForegroundColor','Blue',...
            'Units','Normalized',...
            'Position',[0.005 0.54 0.99 0.11]);
        handles.Showtext=uicontrol(...
            'Parent',handles.ShowPanel,...
            'Style','text',...
            'Units','Normalized',...
            'FontWeight','bold',...
            'horizontalalignment','left',...
            'Position',[0.3 -0.1 0.9 0.8 ],...
            'String','Mode 1 - Mode 2' );
        handles.ChangePlotPanel=uipanel(...
            'Parent',handles.ControlPanel,...
            'FontWeight','bold',...
            'TitlePosition','centertop',...
            'Title','Concatenation dimension',...
            'ForegroundColor','Blue',...
            'Units','Normalized',...
            'Position',[0.005 0.255 0.99 0.28]);
        handles.ButtonSpec = uicontrol(...
            'Parent',handles.ChangePlotPanel,...
            'Style','PushButton',...
            'String','Spectrum',...
            'Units','normalized',...
            'TooltipString','Show Mode 1 - Mode 2 array',...
            'Position',[0.15 0.65 0.75 0.3],...
            'Callback',{@ButtonSpec_Callback});
        handles.ButtonMode1 = uicontrol(...
            'Parent',handles.ChangePlotPanel,...
            'Style','PushButton',...
            'String','Mode 1',...
            'Units','normalized',...
            'TooltipString','Show Frequency - Mode 2 array',...
            'Position',[0.15 0.33 0.75 0.3],...
            'Callback',{@ButtonMode1_Callback});
        handles.ButtonMode2 = uicontrol(...
            'Parent',handles.ChangePlotPanel,...
            'Style','PushButton',...
            'String','Mode 2',...
            'Units','normalized',...
            'TooltipString','Show Frequency - Mode 1 array',...
            'Position',[0.15 0.01 0.75 0.3],...
            'Callback',{@ButtonMode2_Callback});
        %% --- Plot options control
        handles.CheckboxgroupPlot=uipanel(...
            'Parent',handles.ControlPanel,...
            'Units','Normalized',...
            'Title','Plot options',...
            'ForegroundColor','Blue',...
            'TitlePosition','CenterTop',...
            'FontWeight','Bold',...
            'Position',[0.005 0.005 0.6 0.25]);
       handles.CheckboxOriginal = uicontrol(...
            'Parent', handles.CheckboxgroupPlot,...
            'Style','Checkbox',...
            'String','Original',...
            'TooltipString','Display Original spectra',...
            'Units','normalized',...
            'CallBack',{@OriginalCheck_function},...
            'Position',[0.2 0.72 0.9 0.2]);
        handles.CheckboxPARAFAC = uicontrol(...
            'Parent', handles.CheckboxgroupPlot,...
            'Style','Checkbox',...
            'String','PARAFAC',...
            'TooltipString','Display PARAFAC spectra',...
            'Units','normalized',...
            'CallBack',{@PARAFACCheck_function},...
            'Position',[0.2 0.42 0.9 0.2]);
        handles.CheckboxResidual = uicontrol(...
            'Parent', handles.CheckboxgroupPlot,...
            'Style','Checkbox',...
            'String','Residual',...
            'Value',1,...
            'TooltipString','Display residual spectra',...
            'Units','normalized',...
            'CallBack',{@ResidualCheck_function},...
            'Position',[0.2 0.12 0.9 0.2]);
        %% --- Change residual intensity control
        handles.ResidualIntensityPanel=uipanel(...
            'Parent',handles.ControlPanel,...
            'Units','Normalized',...
            'Title','Residual Plot',...
            'ForegroundColor','Blue',...
            'TitlePosition','CenterTop',...
            'FontWeight','Bold',...
            'Position',[0.61 0.005 0.39 0.25]);
        handles.ResidualIntensityDisplay=uicontrol(...
            'Parent',handles.ResidualIntensityPanel,...
            'Style','edit',...
            'Units','Normalized',...
            'BackgroundColor','w',...
            'String',100,...
            'Enable','off',...
            'TooltipString','Current spectrum',...
            'Position',[0.15 0.7 0.65 0.25 ],...
            'CallBack', {@ResidualIntensityDisplay_Callback});
        handles.ButtonMultiply2 = uicontrol(...
            'Parent',handles.ResidualIntensityPanel,...
            'Style','PushButton',...
            'String','x2',...
            'Enable','on',...
            'Units','normalized',...
            'TooltipString','Multiply the intensity of residual plot by 2',...
            'Position',[0.05 0.12 0.45 0.5],...
            'Callback',{@ButtonMultiply2_Callback});
        handles.ButtonDivide2 = uicontrol(...
            'Parent',handles.ResidualIntensityPanel,...
            'Style','PushButton',...
            'String','/2',...
            'Units','normalized',...
            'Enable','on',...
            'TooltipString','Divide the intensity of residual plot by 2',...
            'Position',[0.5 0.12 0.45 0.5],...
            'Callback',{@ButtonDivide2_Callback});
    end
%% FlipPanel Callbacks
    function EditFlip_Callback(source,eventdata)
        %used to display and change the comp displayed
        parres3D=guidata(hs.parresgui);
        parres3D.compnr=round(str2double(get(hs.EditFlip,'String')));
        if parres3D.compnr>parres3D.ncomp
            parres3D.compnr=parres3D.ncomp;
        elseif parres3D.compnr<1
            parres3D.compnr=1;
        elseif isnan(parres3D.compnr)
            disp('unnexpected behaviour - default to one')
            parres3D.compnr=1;
        else
            %all is probably fine
        end
        set(hs.EditFlip,'String',num2str(parres3D.compnr))
        guidata(hs.parresgui,parres3D);
        Display_Callback();
    end
    function ButtonFlipPlus_Callback(source,eventdata)
        %Set which comp decay to plot
        parres3D=guidata(hs.parresgui);
        parres3D.compnr=parres3D.compnr+1;
        set(hs.EditFlip,'String',num2str(parres3D.compnr))
        guidata(hs.parresgui,parres3D);
        EditFlip_Callback();
    end
    function ButtonFlipMinus_Callback(source,eventdata)
        %Set which comp decay to plot
        parres3D=guidata(hs.parresgui);
        parres3D.compnr=parres3D.compnr-1;
        set(hs.EditFlip,'String',num2str(parres3D.compnr))
        guidata(hs.parresgui,parres3D);
        EditFlip_Callback();
    end
%% ChangePlot Callbacks
    function Display_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
        
        % Prealocate temporary data
        parres3D.data_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.parafac_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.res_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.data_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.parafac_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.res_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.data_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        parres3D.parafac_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        parres3D.res_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        
        switch get(hs.ButtongroupDisplay,'SelectedObject')
            case hs.RadioSum
                set(hs.EditFlip,'Enable','off')
                set(hs.ButtonFlipPlus,'Enable','off')
                set(hs.ButtonFlipMinus,'Enable','off')
                
                % Make array for summing direct dimension
                for k=1:parres3D.size_SPECTRUM
                    parres3D.data_tmp_freq=parres3D.data_tmp_freq+squeeze(tmp(k,:,:));
                    parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq+squeeze(parres3D.FINAL(k,:,:));
                    parres3D.res_tmp_freq=parres3D.res_tmp_freq+squeeze(parres3D.residual_spectra(k,:,:));
                end
                parres3D.data_tmp_freq=parres3D.data_tmp_freq./(parres3D.size_SPECTRUM);
                parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq./(parres3D.size_SPECTRUM);
                parres3D.res_tmp_freq=parres3D.res_tmp_freq./(parres3D.size_SPECTRUM);
                
                % Make array for summing MODE1
                for i=1:parres3D.size_MODE1
                    parres3D.data_tmp_1=parres3D.data_tmp_1+squeeze(tmp(:,i,:));
                    parres3D.parafac_tmp_1=parres3D.parafac_tmp_1+squeeze(parres3D.FINAL(:,i,:));
                    parres3D.res_tmp_1=parres3D.res_tmp_1+squeeze(parres3D.residual_spectra(:,i,:));
                end
                parres3D.data_tmp_1=parres3D.data_tmp_1./(parres3D.size_MODE1);
                parres3D.parafac_tmp_1=parres3D.parafac_tmp_1./(parres3D.size_MODE1);
                parres3D.res_tmp_1=parres3D.res_tmp_1./(parres3D.size_MODE1);
                
                % Make array for summing MODE2
                for ii=1:parres3D.size_MODE2
                    parres3D.data_tmp_2=parres3D.data_tmp_2+squeeze(tmp(:,:,ii));
                    parres3D.parafac_tmp_2=parres3D.parafac_tmp_2+squeeze(parres3D.FINAL(:,:,ii));
                    parres3D.res_tmp_2=parres3D.res_tmp_2+squeeze(parres3D.residual_spectra(:,:,ii));
                end
                parres3D.data_tmp_2=parres3D.data_tmp_2./(parres3D.size_MODE2);
                parres3D.parafac_tmp_2=parres3D.parafac_tmp_2./(parres3D.size_MODE2);
                parres3D.res_tmp_2=parres3D.res_tmp_2./(parres3D.size_MODE2);
                
            case hs.RadioRMS
                set(hs.EditFlip,'Enable','off')
                set(hs.ButtonFlipPlus,'Enable','off')
                set(hs.ButtonFlipMinus,'Enable','off')
                
                % Make array for summing direct dimension
                for k=1:parres3D.size_SPECTRUM
                    parres3D.data_tmp_freq=parres3D.data_tmp_freq+(squeeze(tmp(k,:,:))).^2;
                    parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq+(squeeze(parres3D.FINAL(k,:,:))).^2;
                    parres3D.res_tmp_freq=parres3D.res_tmp_freq+(squeeze(parres3D.residual_spectra(k,:,:))).^2;
                end
                parres3D.data_tmp_freq=((parres3D.data_tmp_freq).^0.5)./(parres3D.size_SPECTRUM);
                parres3D.parafac_tmp_freq=((parres3D.parafac_tmp_freq).^0.5)./(parres3D.size_SPECTRUM);
                parres3D.res_tmp_freq=((parres3D.res_tmp_freq).^0.5)./(parres3D.size_SPECTRUM);
                
                % Make array for summing MODE1
                for i=1:parres3D.size_MODE1
                    parres3D.data_tmp_1=parres3D.data_tmp_1+(squeeze(tmp(:,i,:))).^2;
                    parres3D.parafac_tmp_1=parres3D.parafac_tmp_1+(squeeze(parres3D.FINAL(:,i,:))).^2;
                    parres3D.res_tmp_1=parres3D.res_tmp_1+(squeeze(parres3D.residual_spectra(:,i,:))).^2;
                end
                parres3D.data_tmp_1=((parres3D.data_tmp_1).^0.5)./(parres3D.size_MODE1);
                parres3D.parafac_tmp_1=((parres3D.parafac_tmp_1).^0.5)./(parres3D.size_MODE1);
                parres3D.res_tmp_1=((parres3D.res_tmp_1).^0.5)./(parres3D.size_MODE1);
                
                % Make array for summing MODE2
                for ii=1:parres3D.size_MODE2
                    parres3D.data_tmp_2=parres3D.data_tmp_2+(squeeze(tmp(:,:,ii))).^2;
                    parres3D.parafac_tmp_2=parres3D.parafac_tmp_2+(squeeze(parres3D.FINAL(:,:,ii))).^2;
                    parres3D.res_tmp_2=parres3D.res_tmp_2+(squeeze(parres3D.residual_spectra(:,:,ii))).^2;
                end
                parres3D.data_tmp_2=((parres3D.data_tmp_2).^0.5)./(parres3D.size_MODE2);
                parres3D.parafac_tmp_2=((parres3D.parafac_tmp_2).^0.5)./(parres3D.size_MODE2);
                parres3D.res_tmp_2=((parres3D.res_tmp_2).^0.5)./(parres3D.size_MODE2);
                
            case hs.RadioFlip
                counter=round(str2double(get(hs.EditFlip,'String')));
                set(hs.text,'String',['/' num2str(parres3D.ncomp)])
                set(hs.EditFlip,'Enable','on')
                set(hs.ButtonFlipPlus,'Enable','on')
                set(hs.ButtonFlipMinus,'Enable','on')
                
                if parres3D.pmode==0
                    % Get direct dimension
                    k=counter;
                    parres3D.data_tmp_freq=parres3D.data_tmp_freq+squeeze(tmp(k,:,:));
                    parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq+squeeze(parres3D.FINAL(k,:,:));
                    parres3D.res_tmp_freq=parres3D.res_tmp_freq+squeeze(parres3D.residual_spectra(k,:,:));
                    
                elseif parres3D.pmode==1
                    % Get MODE1
                    i=counter;
                    parres3D.data_tmp_1=parres3D.data_tmp_1+squeeze(tmp(:,i,:));
                    parres3D.parafac_tmp_1=parres3D.parafac_tmp_1+squeeze(parres3D.FINAL(:,i,:));
                    parres3D.res_tmp_1=parres3D.res_tmp_1+squeeze(parres3D.residual_spectra(:,i,:));
                    
                elseif parres3D.pmode==2
                    % Get MODE2
                    ii=counter;
                    parres3D.data_tmp_2=parres3D.data_tmp_2+squeeze(tmp(:,:,ii));
                    parres3D.parafac_tmp_2=parres3D.parafac_tmp_2+squeeze(parres3D.FINAL(:,:,ii));
                    parres3D.res_tmp_2=parres3D.res_tmp_2+squeeze(parres3D.residual_spectra(:,:,ii));
                else
                end
                
            otherwise
                disp('Something went wrong. Setting to Sum')
                set(hs.ButtongroupDisplay,'SelectedObject',handles.RadioSum)
                % Make array for summing direct dimension
                for k=1:parres3D.size_SPECTRUM
                    parres3D.data_tmp_freq=parres3D.data_tmp_freq+squeeze(tmp(k,:,:));
                    parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq+squeeze(parres3D.FINAL(k,:,:));
                    parres3D.res_tmp_freq=parres3D.res_tmp_freq+squeeze(parres3D.residual_spectra(k,:,:));
                end
                parres3D.data_tmp_freq=parres3D.data_tmp_freq./(parres3D.size_SPECTRUM);
                parres3D.parafac_tmp_freq=parres3D.parafac_tmp_freq./(parres3D.size_SPECTRUM);
                parres3D.res_tmp_freq=parres3D.res_tmp_freq./(parres3D.size_SPECTRUM);
                
                % Make array for summing MODE1
                for i=1:parres3D.size_MODE1
                    parres3D.data_tmp_1=parres3D.data_tmp_1+squeeze(tmp(:,i,:));
                    parres3D.parafac_tmp_1=parres3D.parafac_tmp_1+squeeze(parres3D.FINAL(:,i,:));
                    parres3D.res_tmp_1=parres3D.res_tmp_1+squeeze(parres3D.residual_spectra(:,i,:));
                end
                parres3D.data_tmp_1=parres3D.data_tmp_1./(parres3D.size_MODE1);
                parres3D.parafac_tmp_1=parres3D.parafac_tmp_1./(parres3D.size_MODE1);
                parres3D.res_tmp_1=parres3D.res_tmp_1./(parres3D.size_MODE1);
                
                % Make array for summing MODE2
                for ii=1:parres3D.size_MODE2
                    parres3D.data_tmp_2=parres3D.data_tmp_2+squeeze(tmp(:,:,ii));
                    parres3D.parafac_tmp_2=parres3D.parafac_tmp_2+squeeze(parres3D.FINAL(:,:,ii));
                    parres3D.res_tmp_2=parres3D.res_tmp_2+squeeze(parres3D.residual_spectra(:,:,ii));
                end
                parres3D.data_tmp_2=parres3D.data_tmp_2./(parres3D.size_MODE2);
                parres3D.parafac_tmp_2=parres3D.parafac_tmp_2./(parres3D.size_MODE2);
                parres3D.res_tmp_2=parres3D.res_tmp_2./(parres3D.size_MODE2);
        end
        
        guidata(hs.parresgui,parres3D)
        subplot_function();
    end
    function OriginalCheck_function(source,eventdata)
        parres3D=guidata(hs.parresgui);
        Opt=parres3D.Opt;
        if get(hs.CheckboxOriginal,'Value')
            Opt(1)=1;
        else
            Opt(1)=0;
        end
        parres3D.Opt=Opt;
        guidata(hs.parresgui,parres3D)
        subplot_function()
    end
    function PARAFACCheck_function(source,eventdata)
        parres3D=guidata(hs.parresgui);
        Opt=parres3D.Opt;
        if get(hs.CheckboxPARAFAC,'Value')
            Opt(2)=1;
        else
            Opt(2)=0;
        end
        parres3D.Opt=Opt;
        guidata(hs.parresgui,parres3D)
        subplot_function()
    end
    function ResidualCheck_function(source,eventdata)
        parres3D=guidata(hs.parresgui);
        Opt=parres3D.Opt;
        if get(hs.CheckboxResidual,'Value')
            Opt(3)=1;
        else
            Opt(3)=0;
        end
        parres3D.Opt=Opt;
        guidata(hs.parresgui,parres3D)
        subplot_function()
    end
    function ButtonSpec_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
        parres3D.pmode=0;
        parres3D.compnr=1;
        set(hs.EditFlip,'String',num2str(parres3D.compnr))
        parres3D.ncomp=parres3D.size_SPECTRUM;
        set(hs.text,'String',['/' num2str(parres3D.ncomp)])
        set(hs.Showtext,'String','Mode 1 - Mode 2')
        guidata(hs.parresgui,parres3D)
        Display_Callback()
    end
    function ButtonMode1_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
        parres3D.pmode=1;
        parres3D.compnr=1;
        set(hs.EditFlip,'String',num2str(parres3D.compnr))
        parres3D.ncomp=parres3D.size_MODE1;
        set(hs.text,'String',['/' num2str(parres3D.ncomp)])
        set(hs.Showtext,'String','Spectrum - Mode 2')
        guidata(hs.parresgui,parres3D)
        Display_Callback()
    end
    function ButtonMode2_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
         parres3D.pmode=2;
         parres3D.compnr=1;
         set(hs.EditFlip,'String',num2str(parres3D.compnr))
         parres3D.ncomp=parres3D.size_MODE2;
        guidata(hs.parresgui,parres3D)
        set(hs.text,'String',['/' num2str(parres3D.ncomp)])
        set(hs.Showtext,'String','Spectrum - Mode 1')
        Display_Callback()
    end
    function ButtonMultiply2_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
        pos=get(gca,'CameraPosition');
        if get(hs.CheckboxResidual,'Value')
            inten=str2double(get(hs.ResidualIntensityDisplay,'String'));
            inten=inten*2;
            set(hs.ResidualIntensityDisplay,'String',num2str(inten))
            parres3D.residual_spectra=((parres3D.residual_spectra).*2);
            guidata(hs.parresgui,parres3D)
            Display_Callback()
        else
        end
        set(gca,'CameraPosition',pos)
    end
    function ButtonDivide2_Callback(source,eventdata)
        parres3D=guidata(hs.parresgui);
        pos=get(gca,'CameraPosition');
        if get(hs.CheckboxResidual,'Value')
            inten=str2double(get(hs.ResidualIntensityDisplay,'String'));
            inten=inten/2;
            if inten<1.5625
                inten=1.5625;
                set(hs.ResidualIntensityDisplay,'String',num2str(inten))
                guidata(hs.parresgui,parres3D)
            else
            set(hs.ResidualIntensityDisplay,'String',num2str(inten))
            parres3D.residual_spectra=((parres3D.residual_spectra)./2);
            guidata(hs.parresgui,parres3D)
            Display_Callback()
            end
        else
        end
        set(gca,'CameraPosition',pos)
    end
%% UTILITY% FUNCTIONS
    function InitiateData()
        parres3D=guidata(hs.parresgui);
        parres3D.Opt=[0 0 1];
        parres3D.pmode=0;
        parres3D.compnr=1;
        parres3D.subplot=1;
        
        % Separate each Factor in appropriate dimension
        parres3D.SPECTRUM=(parafacFac{1});
        parres3D.MODE1=(parafacFac{2});
        parres3D.MODE2=(parafacFac{3});
        parres3D.size_SPECTRUM=size(parres3D.SPECTRUM,1);
        parres3D.size_MODE1=size(parres3D.MODE1,1);
        parres3D.size_MODE2=size(parres3D.MODE2,1);
        parres3D.X=1:1:parres3D.size_MODE2;
        parres3D.Y=1:1:parres3D.size_MODE1;
        %parres3D.Z=1:1:parres3D.size_SPECTRUM;
        parres3D.Z=Ppmscale;
        
        
        % Make each component in a 3D array
        parres3D.FINAL=zeros(size(tmp));
        if ncomp>1
            for x1=1:ncomp
                FINAL_A=zeros(size(tmp));
                for x2=1:parres3D.size_MODE2
                    FINAL_A(:,:,x2)=FINAL_A(:,:,x2)+(((parres3D.SPECTRUM(:,x1))*(parres3D.MODE1(:,x1))').*(parres3D.MODE2(x2,x1)));
                end
                parres3D.FINAL=parres3D.FINAL+FINAL_A;
            end
        else
            return
        end
        
        % Compare original and reconstructed spectra
        parres3D.residual_spectra=(tmp)-(parres3D.FINAL);
        parres3D.plot_res_spectra=real(sum(sum(parres3D.residual_spectra,2),3))./(parres3D.size_MODE1*parres3D.size_MODE2);
        
%         % Generate a 1D with the total residual
%         figure('Name','Residual'); plot(Ppmscale,parres3D.plot_res_spectra,'LineWidth',1.1);xlabel('Total Residual Spectrum')
%         set(gca,'xdir','reverse');
%         axis('tight')
        
        % Prealocate temporary data
        parres3D.data_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.parafac_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.res_tmp_freq=squeeze(zeros(size(tmp(1,:,:))));
        parres3D.data_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.parafac_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.res_tmp_1=squeeze(zeros(size(tmp(:,1,:))));
        parres3D.data_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        parres3D.parafac_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        parres3D.res_tmp_2=squeeze(zeros(size(tmp(:,:,1))));
        
        % Generate mesh for surf plot
        [parres3D.X1,parres3D.Y1]=meshgrid(parres3D.X,parres3D.Y);
        [parres3D.X2,parres3D.Z1]=meshgrid(parres3D.X,parres3D.Z);
        [parres3D.Y2,parres3D.Z2]=meshgrid(parres3D.Y,parres3D.Z);
        
        
        set(hs.Axes,'Visible','on')
        parres3D.ncomp=parres3D.size_SPECTRUM;
        guidata(hs.parresgui,parres3D)
    end
    function subplot_function()
        parres3D=guidata(hs.parresgui);
        
        if parres3D.pmode==0
            %Show Mode 1 - Mode 2
            spec_original=parres3D.data_tmp_freq;
            spec_para=parres3D.parafac_tmp_freq;
            spec_res=parres3D.res_tmp_freq;
            
            axis_X=parres3D.X1;
            axis_Y=parres3D.Y1;
            
        elseif parres3D.pmode==1
            %Show Spectrum - Mode 2
            spec_original=parres3D.data_tmp_1;
            spec_para=parres3D.parafac_tmp_1;
            spec_res=parres3D.res_tmp_1;
            
            axis_X=parres3D.X2;
            axis_Y=parres3D.Z1;
            
        elseif parres3D.pmode==2
            %Show Spectrum - Mode 1
            spec_original=parres3D.data_tmp_2;
            spec_para=parres3D.parafac_tmp_2;
            spec_res=parres3D.res_tmp_2;
            
            axis_X=parres3D.Y2;
            axis_Y=parres3D.Z2;
            
        else %something went wrong, I will consider parres3D.pmode==0
            parres3D.pmode=0;
            
            spec_original=parres3D.data_tmp_freq;
            spec_para=parres3D.parafac_tmp_freq;
            spec_res=parres3D.res_tmp_freq;
            
            axis_X=parres3D.X1;
            axis_Y=parres3D.Y1;
            
        end
        
        if parres3D.subplot==1
            cla(hs.Axes,'reset')
            set(hs.Axes,'Visible','off')
            plot_residual=findobj(hs.Axes,'Tag','Residual');
            delete(plot_residual)
            plot_original=findobj(hs.Axes,'Tag','Original');
            delete(plot_original)
            plot_parafac=findobj(hs.Axes,'Tag','PARAFAC');
            delete(plot_parafac)
            set(hs.Axes,'HitTest','off')
            set(hs.Axes,'PickableParts','none')
            axis(hs.Axes,'off')
        elseif parres3D.subplot==2
            cla(hs.Axes21,'reset')
            cla(hs.Axes22,'reset')
            set(hs.Axes21,'Visible','off')
            set(hs.Axes22,'Visible','off')
            plot_residual=findobj(hs.Axes21,'Tag','Residual');
            delete(plot_residual)
            plot_original=findobj(hs.Axes21,'Tag','Original');
            delete(plot_original)
            plot_original=findobj(hs.Axes22,'Tag','Original');
            delete(plot_original)
            plot_parafac=findobj(hs.Axes22,'Tag','PARAFAC');
            delete(plot_parafac)
            Link2=findobj('Tag','Link2');
            delete(Link2)
            set(hs.Axes21,'HitTest','off')
            set(hs.Axes21,'PickableParts','none')
            axis(hs.Axes21,'off')
            set(hs.Axes22,'HitTest','off')
            set(hs.Axes22,'PickableParts','none')
            axis(hs.Axes22,'off')
        elseif parres3D.subplot==3
            cla(hs.Axes31,'reset')
            set(hs.Axes31,'Visible','off')
            cla(hs.Axes32,'reset')
            set(hs.Axes32,'Visible','off')
            cla(hs.Axes33,'reset')
            set(hs.Axes33,'Visible','off')
            plot_residual=findobj(hs.Axes31,'Tag','Residual');
            delete(plot_residual)
            plot_original=findobj(hs.Axes32,'Tag','Original');
            delete(plot_original)
            plot_parafac=findobj(hs.Axes33,'Tag','PARAFAC');
            delete(plot_parafac)
            Link3=findobj('Tag','Link3');
            delete(Link3)
            set(hs.Axes31,'HitTest','off')
            set(hs.Axes31,'PickableParts','none')
            axis(hs.Axes31,'off')
            set(hs.Axes32,'HitTest','off')
            set(hs.Axes32,'PickableParts','none')
            axis(hs.Axes32,'off')
            set(hs.Axes33,'HitTest','off')
            set(hs.Axes33,'PickableParts','none')
            axis(hs.Axes33,'off')
        end
        
        guidata(hs.parresgui,parres3D)
        parres3D=guidata(hs.parresgui);
        
        Opt=parres3D.Opt;
        X=sum(parres3D.Opt); %number of subpectra
        if X==1
            axes(hs.Axes)
            set(hs.Axes,'Visible','on')
            ax1 = subplot(1,1,1,hs.Axes);
            if Opt(1) == 1
                surf(ax1,axis_X,axis_Y,spec_original,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','Original');title('Original')
            elseif Opt(2)== 1
                surf(ax1,axis_X,axis_Y,spec_para,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','PARAFAC');title('PARAFAC')
            elseif Opt(3) == 1
                surf(ax1,axis_X,axis_Y,spec_res,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','Residual');title('Residual')
            end
            colormap(jet);
            set(hs.Axes,'HitTest','on')
            set(hs.Axes,'PickableParts','all')
            
        elseif X==2
            axes(hs.Axes21)
            set(hs.Axes21,'Visible','on')
            axes(hs.Axes22)
            set(hs.Axes22,'Visible','on')
            if Opt(1) == 1
                ax21 = subplot(2,1,1,hs.Axes21);
                surf(ax21,axis_X,axis_Y,spec_original,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','Original');title('Original')
                hold on
                ax22 = subplot(2,1,2,hs.Axes22);
                if Opt(2) == 1
                    surf(ax22,axis_X,axis_Y,spec_para,...
                        'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                        'Tag','PARAFAC');title('PARAFAC')
                    hold on
                elseif Opt(3) == 1
                    surf(ax22,axis_X,axis_Y,spec_res,...
                        'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                        'Tag','Residual');title('Residual')
                    hold on
                end
            elseif Opt(1) == 0
                ax21 = subplot(2,1,1,hs.Axes21);
                surf(ax21,axis_X,axis_Y,spec_para,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','PARAFAC');title('PARAFAC')
                hold on
                ax22 = subplot(2,1,2,hs.Axes22);
                surf(ax22,axis_X,axis_Y,spec_res,...
                    'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                    'Tag','Residual');title('Residual')
                hold on
            end
            colormap(ax21,jet);colormap(ax22,jet);
            Link2 = linkprop([ax21,ax22],{'CameraUpVector', 'CameraPosition', 'CameraTarget', 'XLim', 'YLim', 'ZLim'},'Tag','Link2');
            setappdata(gcf, 'StoreTheLink', Link2);
            set(hs.Axes21,'HitTest','on')
            set(hs.Axes21,'PickableParts','all')
            set(hs.Axes22,'HitTest','on')
            set(hs.Axes22,'PickableParts','all')
            
        elseif X==3
            axes(hs.Axes31)
            set(hs.Axes31,'Visible','on')
            axes(hs.Axes32)
            set(hs.Axes32,'Visible','on')
            axes(hs.Axes33)
            set(hs.Axes33,'Visible','on')
            ax31 = subplot(3,1,1,hs.Axes31);surf(ax31,axis_X,axis_Y,spec_original,...
                'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                'Tag','Original');title(ax31,'Original')
            hold on
            ax32 = subplot(3,1,2,hs.Axes32);surf(ax32,axis_X,axis_Y,spec_para,...
                'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                'Tag','PARAFAC');title(ax32,'PARAFAC')
            hold on
            ax33 = subplot(3,1,3,hs.Axes33);surf(ax33,axis_X,axis_Y,spec_res,...
                'EdgeColor','none','LineStyle','-','LineWidth',1,'FaceColor','interp','FaceLighting','none',...
                'Tag','Residual');title(ax33,'Residual')
            hold on
            colormap(ax31,jet);colormap(ax32,jet);colormap(ax33,jet)
            Link3 = linkprop([ax31,ax32,ax33],{'CameraUpVector', 'CameraPosition', 'CameraTarget', 'XLim', 'YLim', 'ZLim'},'Tag','Link3');
            setappdata(gcf, 'StoreTheLink', Link3);
            set(hs.Axes31,'HitTest','on')
            set(hs.Axes31,'PickableParts','all')
            set(hs.Axes32,'HitTest','on')
            set(hs.Axes32,'PickableParts','all')
            set(hs.Axes33,'HitTest','on')
            set(hs.Axes33,'PickableParts','all')
        else
        end
        
        parres3D.subplot=X;
        guidata(hs.parresgui,parres3D)

    end
end