function varargout = ViewReaction(varargin)
% ViewReaction takes
%                        a MATLAB_SBMLReaction structure
%                 and drives a GUI that illustrates the reaction structure fields and values 
%
% VIEWREACTION M-file for ViewReaction.fig
%
%
%  The original code contained here was initially developed by:
%                              Slava Chushak,  BHSAI,USAMRMC  at AFRL/HEPB
%
%      VIEWREACTION('Property','Value',...) creates a new VIEWREACTION or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before ViewReaction_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to ViewReaction_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 ViewReaction

% Last Modified by GUIDE v2.5 01-Feb-2006 12:11:25

% Begin initialization code - DO NOT EDIT
gui_Singleton = 0;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @ViewReaction_OpeningFcn, ...
                   'gui_OutputFcn',  @ViewReaction_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin & isstr(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 ViewReaction is made visible.
function ViewReaction_OpeningFcn(hObject, eventdata, handles, varargin)
% 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 ViewReaction (see VARARGIN)

% get the input argument and assign to the handle
Reaction = varargin{1};
handles.Reaction = Reaction;

% keep initial values

handles.initReaction = Reaction;

% determine sbml level
if (isSBML_Reaction(Reaction, 1))
    Level = 1;
elseif (isSBML_Reaction(Reaction, 2))
    Level = 2;
else
    error('Structure supplied is not a SBML Reaction');
end;
handles.Level = Level;

% Set reaction name

if (Level == 1) 
    set(handles.React_name, 'String', Reaction.name);
else
   
    % determine whether the optional name field has a value
    if (isempty(Reaction.name))   
        set(handles.React_name, 'String', Reaction.id);
    else
        set(handles.React_name, 'String', Reaction.name);
    end;
end

% Set Kinetic Law
   
    set(handles.Law_edit, 'String', handles.Reaction.kineticLaw.formula);
% Set reactants and products lists

   [Reactants ReactantsStoich Products ProductsStoich] = GetReactSpecies(Reaction,Level);

    NumReact = length(ReactantsStoich);
for i = 1:NumReact
    ListReact(i) = Reactants(i);
end;

handles.ListReact = ListReact;
set(handles.menu_react, 'String', ListReact);
handles.ReactIndex = 1;
handles.ReactantsStoich = ReactantsStoich;
handles.initReactStoich = ReactantsStoich;

set(handles.edit_react, 'String', num2str(handles.ReactantsStoich(handles.ReactIndex)));

    NumProd = length(ProductsStoich);
for i = 1:NumProd
    ListProd(i) = Products(i);
end;

handles.ListProd = ListProd;
set(handles.menu_prod, 'String', ListProd);
handles.ProdIndex = 1;
handles.ProductsStoich = ProductsStoich;
handles.initProdStoich = ProductsStoich;

set(handles.edit_prod, 'String', num2str(handles.ProductsStoich(handles.ProdIndex),6));

% Set constants list
   Constants = [];
   ConstantsValue = [];
   [Constants ConstantsValue] = GetConstants(Reaction,Level);

    NumConstants = length(ConstantsValue);
for i = 1:NumConstants
    ListConst(i) = Constants(i);
end;

handles.ListConst = ListConst;
set(handles.Const_menu, 'String', ListConst);
handles.ConstantIndex = 1;
handles.ConstantsValue = ConstantsValue;
handles.initConstants = ConstantsValue;

set(handles.Const_edit, 'String', num2str(handles.ConstantsValue(handles.ConstantIndex),6));

% Update handles structure
guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = ViewReaction_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)

%--------------------------------------------------------------------------
% assign output

    varargout{1} = handles.Reaction;
    
    close(handles.figure1); 

% --- Executes on selection change in Const_menu.
function Const_menu_Callback(hObject, eventdata, handles)
% hObject    handle to Const_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns Const_menu contents as cell array
%        contents{get(hObject,'Value')} returns selected item from Const_menu

handles.ConstantIndex = get(handles.Const_menu, 'Value');
set(handles.Const_edit, 'String', num2str(handles.ConstantsValue(handles.ConstantIndex),6));
% Update handles structure
guidata(hObject, handles);


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

% Hint: popupmenu 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 Law_edit_Callback(hObject, eventdata, handles)
% hObject    handle to Const_edit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of Const_edit as text
%        str2double(get(hObject,'String')) returns contents of Const_edit as a double

value = get(hObject, 'String');
  
    if isempty(value)
        errordlg(' You have entered an empty string !!!','Error in Parameter Value');
        return
    else
        handles.Reaction.kineticLaw.formula = value;
    end
% Update handles structure
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function Law_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Const_edit (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 Const_edit_Callback(hObject, eventdata, handles)
% hObject    handle to Const_edit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of Const_edit as text
%        str2double(get(hObject,'String')) returns contents of Const_edit as a double


value = str2double(get(handles.Const_edit, 'String'));
   
    if isnan(value) || value < 0
        errordlg(' Please, check the entered value','Error in Parameter Value');
        return
    else
        handles.ConstantsValue(handles.ConstantIndex) = value;
        handles.Reaction.kineticLaw.parameter(handles.ConstantIndex).value = value;
    end
    
% Update handles structure
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function Const_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Const_edit (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 button press in OK_button.
function OK_button_Callback(hObject, eventdata, handles)
% hObject    handle to OK_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    
%  close the GUI    
    
    if isequal(get(handles.figure1, 'waitstatus'), 'waiting')
    % The GUI is still in UIWAIT, us UIRESUME
    uiresume(handles.figure1);
else
    % The GUI is no longer waiting, just close it
    delete(handles.figure1);
end


% --- Executes on button press in Cancel_button.
function Cancel_button_Callback(hObject, eventdata, handles)
% hObject    handle to Cancel_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%--------------------------------------------------------------------------
% assign output

     handles.Reaction = handles.initReaction;
    % Update handles structure
    guidata(hObject, handles);

% close the gui

if isequal(get(handles.figure1, 'waitstatus'), 'waiting')
    % The GUI is still in UIWAIT, us UIRESUME
    uiresume(handles.figure1);
else
    % The GUI is no longer waiting, just close it
    delete(handles.figure1);
end


% --- Executes on button press in Reset.
function Reset_Callback(hObject, eventdata, handles)
% hObject    handle to Reset (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

handles.Reaction = handles.initReaction;
handles.ConstantsValue = handles.initConstants;
handles.ReactantsStoich = handles.initReactStoich;
handles.ProductsStoich = handles.initProdStoich;

% Update handles structure
guidata(hObject, handles);

% Set Kinetic Law
   
    set(handles.Law_edit, 'String', handles.Reaction.kineticLaw.formula);
    handles.ConstantIndex = get(handles.Const_menu, 'Value');
    set(handles.Const_edit, 'String', num2str(handles.ConstantsValue(handles.ConstantIndex),6));
    handles.ReactIndex = get(handles.menu_react, 'Value');
    set(handles.edit_react, 'String', num2str(handles.ReactantsStoich(handles.ReactIndex),6));
    handles.ProdIndex = get(handles.menu_prod, 'Value');
    set(handles.edit_prod, 'String', num2str(handles.ProductsStoich(handles.ProdIndex),6));

    
    % --- Executes on selection change in menu_react.
function menu_react_Callback(hObject, eventdata, handles)
% hObject    handle to menu_react (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns menu_react contents as cell array
%        contents{get(hObject,'Value')} returns selected item from menu_react

    handles.ReactIndex = get(handles.menu_react, 'Value');
    set(handles.edit_react, 'String', num2str(handles.ReactantsStoich(handles.ReactIndex),6));

% Update handles structure
guidata(hObject, handles);

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

% Hint: popupmenu 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 edit_react_Callback(hObject, eventdata, handles)
% hObject    handle to edit_react (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_react as text
%        str2double(get(hObject,'String')) returns contents of edit_react as a double

value = str2num(get(handles.edit_react, 'String'));
   
    if isnan(value) || value < 0
        errordlg(' Please, check the entered value','Error in Parameter Value');
        return
    else
        handles.ReactantsStoich(handles.ReactIndex) = value;
        handles.Reaction.reactant(handles.ReactIndex).stoichiometry = value;
    end
    
% Update handles structure
guidata(hObject, handles);


% --- Executes during object creation, after setting all properties.
function edit_react_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_react (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 menu_prod.
function menu_prod_Callback(hObject, eventdata, handles)
% hObject    handle to menu_prod (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns menu_prod contents as cell array
%        contents{get(hObject,'Value')} returns selected item from menu_prod

    handles.ProdIndex = get(handles.menu_prod, 'Value');
    set(handles.edit_prod, 'String', num2str(handles.ProductsStoich(handles.ProdIndex),6));

% Update handles structure
guidata(hObject, handles);

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

% Hint: popupmenu 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 edit_prod_Callback(hObject, eventdata, handles)
% hObject    handle to edit_prod (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_prod as text
%        str2double(get(hObject,'String')) returns contents of edit_prod as a double

value = str2num(get(handles.edit_prod, 'String'));
   
    if isnan(value) || value < 0
        errordlg(' Please, check the entered value','Error in Parameter Value');
        return
    else
        handles.ProductsStoich(handles.ProdIndex) = value;
        handles.Reaction.product(handles.ProdIndex).stoichiometry = value;
    end
    
% Update handles structure
guidata(hObject, handles);


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


   
%---------------------------------------------------------------
%            Other Functions
%---------------------------------------------------------------

function varargout = GetConstants(Reaction, Level)
% GetConstants takes a Reaction from SBML Model 
% and returns 
%           1) an array of character names of all reaction constants 
%           2) an array of values of each constant
%
%      Created by Slava Chushak        27/12/05


%------------------------------------------------------------
% determine the number of constants in the Reaction
NumConstants = length(Reaction.kineticLaw.parameter);

%------------------------------------------------------------
% loop through the list of paraneters
for i = 1:NumConstants
    if (Level == 1)
       name = Reaction.kineticLaw.parameter(i).name;
    else
        name = Reaction.kineticLaw.parameter(i).id;
    end
    CharArray{i} = name;
    
    % get the values and add to an array
    
    Values(i) = Reaction.kineticLaw.parameter(i).value;
    
end;

%--------------------------------------------------------------------------
% assign output

if (NumConstants ~= 0)
    varargout{1} = CharArray;
    varargout{2} = Values;
else
    varargout{1} = 'NO Constants';
    varargout{2} = '-';
end;

% =======================================================================

function varargout = GetReactSpecies(Reaction, Level)
% GetReactSpecies takes a Reaction from SBML Model 
% and returns 
%           1) an arrays of character names of all reactants and products 
%           2) an arrays of stoichiometry of each components
%
%      Created by Slava Chushak        01/26/06


%------------------------------------------------------------
% determine the number of reactants and products in the Reaction
NumReact = length(Reaction.reactant);
NumProd = length(Reaction.product);
%------------------------------------------------------------
% loop through the list of reactants
for i = 1:NumReact
       name = Reaction.reactant(i).species;
       ReactArray{i} = name;
    
    % get the values and add to an array
    
       ReactValues(i) = double(Reaction.reactant(i).stoichiometry);    
end;

% loop through the list of products
for i = 1:NumProd
       name = Reaction.product(i).species;
       ProdArray{i} = name;
    
      % get the values and add to an array
    
    ProdValues(i) = double(Reaction.product(i).stoichiometry);    

end
    

%--------------------------------------------------------------------------
% assign output

if (NumReact ~= 0)
    varargout{1} = ReactArray;
    varargout{2} = ReactValues;
else
    varargout{1} = 'NO Reactants';
    varargout{2} = '-';
end;

if (NumProd ~= 0)
    varargout{3} = ProdArray;
    varargout{4} = ProdValues;
else
    varargout{3} = 'NO Products';
    varargout{4} = '-';
end;

