% Author: Elsa W. Birch, ewbirch@stanford.edu, Covert Lab - Stanford Bioengineering
% Date: 4/24/2011
% Version: associated with production of the figures for Birch et al. 2012 
%
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
%
% Summary: This function runs timecourse of simulation as specified in simulation options.
%          It loops over all timesteps and within that organisms, updating media with each
%          time iteration. Updates on simulation progress are written to command line at a
%          frequency specified by input.
% 
%
% Inputs:   simulation - integrated simulation structure, infected or uninfected, or with multiple organisms
%			nUpdates - niteger number of text ouputs with percentage of timesteps complete to output durring simulation evaluation, if zero then no output
%
% Outputs:  simulationRun - structure of simulation models and including results of evaluation accross time
%
%
%
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
%
% Notes: 
%
%
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


function simulationRun = FBA_EB_simulationRun(simulation, nUpdates)

% run simualtion
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

% try running simulation, if error, will be thrown after 
try
    
    while simulation.iSim < simulation.nTimesteps

        % update simualtion iteration
        simulation.iSim = simulation.iSim + 1;

        % allocate current nutritional resources between organisms
        [ mediaPerOrganism ] = FBA_EB_mediaAllocateSimpleProportion(simulation);
        mediaConsumptionPerOrganism = zeros( simulation.nMedia, simulation.nOrganism );

        for iSimOrg = 1 : simulation.nOrganism        
            
            
            modularStepFn = simulation.( simulation.organismList{ iSimOrg } ).methods.modularSingleStepHandle;
            
            [simulation.(simulation.organismList{iSimOrg}).simulation, ...
             mediaConsumptionPerOrganism(:,iSimOrg)] = ...
                modularStepFn(simulation.tStep, simulation.iSim, ...
                simulation.(simulation.organismList{iSimOrg}), mediaPerOrganism(:,iSimOrg), ...
                simulation.(simulation.organismList{iSimOrg}).simulation.stimuli(:,simulation.iSim) );
            
            
        end % for each organism

        % update media
        simulation.media(:,simulation.iSim) = simulation.media(:,simulation.iSim-1) ...
            + sum( mediaConsumptionPerOrganism, 2 );

        % replace freely exchanged media components
        simulation.media(simulation.freeExchangeMediaIdx,simulation.iSim) = simulation.freeExchangeMedia;
        
        % remove any negative concentrations that may have been created by bounding of
        % uptake using initial biomass concentration 
        simulation.media(:,simulation.iSim) = max( 0 , simulation.media(:,simulation.iSim));
        
        % progress output to command line
        if nUpdates > 0
            progressUpdate = round(simulation.nTimesteps/nUpdates);
            if mod(simulation.iSim,progressUpdate) == 0
                percentDone = round(simulation.iSim / simulation.nTimesteps * 100);
                disp(['|    ',num2str(percentDone),'% of timespteps completed'])
            end % 
        end % if any updates

    end % while

    simulationRun = simulation;
    
catch exceptionSimulation 
    
    
    rethrow( exceptionSimulation )
    
end % try running simulation






