function varargout = mitm_viewer( filename, varargin )
%MITM_VIEWER More-Image-Than-Memory complex image viewer
%   MITM_VIEWER (FILENAME, 'PropertyName', PropertyValue, ...) takes a
%   file of complex data (or set of files of identical sizes) and displays
%   them in a MATLAB IMSHOW/IMAGESC style viewer, even if the file is too
%   large to fit into memory.  Any file type handled by OPEN_READER can be
%   used.
%
%   Really just a convenient GUI wrapper for the HG_MITM_VIEWER component.
%
%       Property name     Description
%       figureSize        Size of the figure to be drawn (if a new figure
%                         is to be created).  If figureSize is not
%                         specified, the largest figure size that will fit
%                         in the current screen with an integer zoom factor
%                         is used.  This propert is ignored if the parent
%                         property is set.
%       initialFrame      Set the initial frame viewed.  Default is 1.
%       initialRemap      Set the initial remap function.  Default is
%                         'densityremap'.
%       mode              'navigate' (default), 'aoi', 'points', or
%                         'polygon'. Navigate just browses images.  'aoi'
%                         adds a button that allows the users to select a
%                         rectangular AOI which is returned as the output
%                         parameter.  'points' selects a single point or
%                         set of points in the image.  'polygon' actually
%                         behaves the same as 'points' with an indefinite
%                         number points, but draws lines between the
%                         points.
%       numPoints         If mode is 'points', this is the number of points
%                         to select.  Default is 1.  Setting to 0 or Inf
%                         will allow an indefinite number of points (same
%                         use as MATLAB getpts function).  If mode is not
%                         'points', this parameter is ignored.
%       selectCallback    Function handle for function that should be run
%                         after selection.  Callback is a function that
%                         takes a single argument, the selection
%                         parameters.  If selectCallback is set, multiple
%                         AOI/points can be chosen.  If not, only one
%                         AOI/point is chosen and returned in the output
%                         argument.
%       closeAfterSelect  Default is false.  Determines whether the figure
%                         should close after the AOI/point is chosen.  If
%                         mode is 'navigate', or if parent or
%                         selectCallback are set, then this property is
%                         ignored.
%       undulationFilename   The name/path of the file containing WGS84 to
%                            geoid undulations.  This is used in the data
%                            cursor (see geoid_undulation) to display
%                            the height above ellipsoid rather then height
%                            above mean sea level.  If the file doesn't
%                            exist no HOE measurement is shown.
%
% Author: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

%% Parse input parameters
p = inputParser;
p.KeepUnmatched=true;
p.addParamValue('figureSize', [], @(x) isequal(size(x),[1 2])||isequal(size(x),[2 1]));
p.addParamValue('mode', 'navigate', @(x) any(strcmpi(x,{'navigate', 'aoi', 'points','polygon'})));
p.addParamValue('numPoints',1,@(x) isscalar(x));
p.addParamValue('initialFrame',1, @(x) isscalar(x)&&isnumeric(x)&&(x>0));
p.addParamValue('initialRemap',[], @(x) exist(x)>0);
p.addParamValue('closeAfterSelect', false);
p.addParamValue('selectCallback',[],@(x) isempty(x)||isa(x,'function_handle'))
p.addParamValue('undulationFilename', 'Und_min2.5x2.5_egm2008_isw=82_WGS84_TideFree_SE');
p.FunctionName = 'MITM_VIEWER';
p.parse(varargin{:});

%% Open files
if ((nargin<1)||isempty(filename)) % If no filename was give, use dialog box to ask for one
    % Recall last interactively selected path used
    if ispref('matlab_sar_toolbox','last_used_directory')
        pathname = getpref('matlab_sar_toolbox','last_used_directory');
        if ~ischar(pathname)||~exist(pathname,'dir')
            pathname = pwd;
        end
    else
        pathname = pwd;
    end
    [filename,pathname]=uigetfile(sar_file_extensions('complex'),...
        'Select Input File', pathname,'MultiSelect','on');
    if(iscell(filename)), filename=sort(filename); end;
    setpref('matlab_sar_toolbox','last_used_directory',pathname);
else
    pathname=[];
end
if(isinmem(filename)) % Filename is actually an array in memory
    fullfilename{1}=filename;
elseif(iscell(filename)) % Multiple files requested
    for i=1:length(filename)
        fullfilename{i}=[pathname filename{i}];
    end
elseif(filename) % Single filename
    fullfilename{1}=[pathname filename];
else % filename=0.  Cancel was pressed, instead of a file being chosen.
    if ~strcmpi(p.Results.mode,'navigate')
        varargout={[],1};
    end
    return;
end

%% Setup layout
fig_hand=figure('MenuBar','none','Toolbar','none');
uip_hand = uipanel('Parent',fig_hand,'Position',[0 0 1 1],'BorderType','none');
mitm_hand = hg_mitm_viewer(uip_hand);
% Save image button
saveButton=javaObjectEDT('javax.swing.JButton');
saveButton.setIcon(javaObjectEDT('javax.swing.ImageIcon',...
    fullfile(toolboxdir('matlab'),['icons' filesep 'file_save.png'])));
saveButton.setToolTipText('Save As...');
saveButton.setFocusable(false); % Make consistent with MATLAB toolbars
set(handle(saveButton,'callbackproperties'),'ActionPerformedCallback',...
    @(hbutton, eventStruct, hfig) save_image());
% Metadata button
metaButton=javaObjectEDT('javax.swing.JButton','Metadata');
set(handle(metaButton,'callbackproperties'),'ActionPerformedCallback',@(obj,eventdata) show_metadata());
% Geojump button
geojumpButton=javaObjectEDT('javax.swing.JButton','Geojump');
set(handle(geojumpButton,'callbackproperties'),'ActionPerformedCallback',@(obj,eventdata) geojump());
% AOI button
if ~strcmpi(p.Results.mode,'navigate')
    switch lower(p.Results.mode)
        case 'aoi'
            button_str = 'Select AOI';
        case 'points'
            button_str = 'Select point(s)';
        case 'polygon'
            button_str = 'Select polygon';
    end
    aoiButton=javaObjectEDT('javax.swing.JButton',button_str);
    set(handle(aoiButton,'callbackproperties'),'ActionPerformedCallback',@(obj,eventdata) select_AOI());
end

% Open file
mitm_hand.Frame = p.Results.initialFrame;
mitm_hand.openFile(fullfilename, true);
metadata = mitm_hand.Metadata;

% Add buttons to toolbar
main_toolbar = mitm_hand.main_toolbar;
main_toolbar.addSeparator;
main_toolbar.add(metaButton);
try
    if ~isempty(point_slant_to_ground([1; 1], metadata{mitm_hand.Frame}))
        main_toolbar.add(geojumpButton);
    end
end
if(~strcmpi(p.Results.mode,'navigate'))
    main_toolbar.addSeparator;
    main_toolbar.add(aoiButton);
end
main_toolbar.addSeparator;
main_toolbar.add(saveButton);
main_toolbar.repaint;
main_toolbar.revalidate;

%% Set figure size appropriate for data
datasize=double([metadata{mitm_hand.Frame}.ImageData.NumCols metadata{mitm_hand.Frame}.ImageData.NumRows]);
if numel(metadata)==1 % Ugly.  Hardcoded to match the toolbar height found in hg_mitm_viewer.
    toolbar_height = 25;
else
    toolbar_height = 50;
end
if isempty(p.Results.figureSize)
    screensize=get(0,'ScreenSize');
    % Image must fit in full screen size minus toolbars and border
    max_img_size=((screensize(3:4)-screensize(1:2))-[0 toolbar_height]) - [20 50];
else
    max_img_size=p.Results.figureSize;
end
if isfield(metadata{mitm_hand.Frame},'CollectionInfo')&&...
        isfield(metadata{mitm_hand.Frame}.CollectionInfo,'CoreName')
    fig_name_str = metadata{mitm_hand.Frame}.CollectionInfo.CoreName;
elseif (numel(metadata)>1)
    fig_name_str = ['Image #' num2str(mitm_hand.Frame)];
else
    fig_name_str = '';
end
scale = max(ceil(datasize./max_img_size)); % Initial scale is lowest integer decimation that will fit
% Calculation of desired size is very specific to internal workings of hg_mitm_viewer
new_size = ceil(datasize./scale) + [0 toolbar_height] + 1;
set(fig_hand,'Name',fig_name_str,'Position',[20 20 new_size]);
% The resize callback executes in parallel with the current code.  Make
% sure resize completes, before we continue, since the following zoom is
% dependent on the new size.
tid = tic;
while(~isequal(getpixelposition(fig_hand),[20 20 new_size]))&&(toc(tid)<1)
end
mitm_hand.Zoom = 'fit';
if ~isempty(p.Results.initialRemap)
    mitm_hand.Remap = p.Results.initialRemap;
end

%% Will selection parameters be returned in output argument?  If so, wait
if(~strcmpi(p.Results.mode,'navigate')&&isempty(p.Results.selectCallback))
    % Should disable metadata button here until AOI selection is finished
    waitfor(uip_hand,'UserData','AOI_finished');
    if(~exist('varargout','var'))
        varargout={[],1};
    end
end

%% Callbacks for figure toolbar button functions
    % All of the work here is temporarily removing the toolbar from the
    % figure, so it doesn't get saved.  We assume that we must have a
    % figure with nothing else other than the mitm_viewer.
    function save_image()
        old_resize = get(uip_hand,'ResizeFcn');
        old_visible = get(mitm_hand.movie_toolbar,'Visible');
        set(uip_hand,'ResizeFcn',[]);
        fig_pos = getpixelposition(fig_hand);
        axes_pos = getpixelposition(mitm_hand.AxesHandle);
        setpixelposition(fig_hand,[fig_pos(1:2) axes_pos(3:4)]);
        setpixelposition(mitm_hand.AxesHandle,axes_pos);
        filemenufcn(fig_hand,'FileSaveAs');
        set(mitm_hand.movie_toolbar,'Visible',old_visible); % Why does FileSaveAs change this?
        set(uip_hand,'ResizeFcn',old_resize);
        setpixelposition(fig_hand,fig_pos); % Replace toolbar
    end

    % Roughly the reverse of complexdatacursorfun.  Takes a lat/long and
    % places a datacursor-- as opposed to complexdatacursorfun which takes
    % a datacursor and computes a lat/long.
    function geojump()
        full_meta = mitm_hand.Metadata;
        meta = full_meta{mitm_hand.Frame}; % For easier referencing
        % Get lat/long from user
        if isfield(meta,'GeoData')&&isfield(meta.GeoData,'SCP')
            % Default elevation is elevation of scene center
            def_el = num2str(meta.GeoData.SCP.LLH.HAE);
        else
            def_el = '';
        end
        answers = inputdlg({'Latitude','Longitude','Elevation (HAE, m)'},'Geojump',1,{'','',def_el});
        if isempty(answers), return, end; % Cancel was pressed
        lla = [latlonnum(answers{1});...
            latlonnum(answers{2});...
            str2double(answers{3})];
        if any(isnan(lla))
            msgbox('Invalid Lat/Lon format!');
            return;
        end
        if ~mitm_hand.geojump(lla)
            msgbox('Specified point is not in image!');
        end
    end

    % Display image metadata
    function show_metadata
        % Just opens the MATLAB variable editor for the metadata.  Assumes
        % user is at the MATLAB commandline with no debugger.
        % assignin('base','metadata',metadata{mitm_hand.Frame});
        % openvar('metadata');
        % Brings up new figure with tree view of metadata
        % Doesn't handle cell arrays or display 2-D matrices as well as
        % the MATLAB variable editor, but cleaner because its standalone
        % and doesn't write to base MATLAB workspace.
        MetaViewer(metadata{mitm_hand.Frame});
    end

    function select_AOI
        % Get AOI
        if strcmpi(p.Results.mode,'aoi') % Rectangular AOI
            aoi_screen=[0 0 0 0];
            while(any(aoi_screen(3:4)==0)),
                aoi_screen=getrect(mitm_hand.AxesHandle);
            end
        elseif strcmpi(p.Results.mode,'polygon')
            [x,y]=getline(mitm_hand.AxesHandle);
        elseif (p.Results.numPoints>0)&&isfinite(p.Results.numPoints) % Predetermined number of points
            [x,y]=ginput(p.Results.numPoints);
        else % Indefinite number of points
            [x,y]=getpts(mitm_hand.AxesHandle);
        end
        % Draw AOI
        if strcmpi(p.Results.mode,'aoi')
            h=rectangle('Position',aoi_screen,'LineWidth',2,'EdgeColor','r');
        elseif strcmpi(p.Results.mode,'polygon')
            h=line([x; x(1)],[y; y(1)],zeros(size(x)+[1 0]),'Color', 'r', 'LineWidth', 2);
        else % Points
            % Emulate getpts-style markers
            h=line(x,y,zeros(size(x)),'Color', 'c', 'LineStyle', 'none', 'Marker', '+', 'MarkerSize', 9);
            h2=line(x,y,'Color', 'm', 'LineStyle', 'none', 'Marker', 'x', 'MarkerSize', 9);
        end
        % Confirm selection
        if ~strcmpi(p.Results.mode,'aoi')
            if p.Results.numPoints~=1
                question_string='Are these the points you wish to select?';
            else
                question_string='Is this the point you wish to select?';
            end
        else
            question_string='Is this the area of interest you wish to select?';
        end
        button=questdlg(question_string,'Confirm AOI','Yes','No','Yes');
        if(strcmp(button,'Yes'))
            varargout={[],1};
            % Convert to image coordinate space
            if strcmpi(p.Results.mode,'aoi')
                ulcorner=round(mitm_hand.axescoords2native(aoi_screen(1:2)));
                lrcorner=round(mitm_hand.axescoords2native(aoi_screen(1:2) + aoi_screen(3:4) - 1));
                % Constrain to be within image dimensions
                ulcorner=max(1,ulcorner);
                lrcorner=min(datasize,lrcorner);
                % Return values (UL corner and size) to calling function
                varargout{1}(1:2)=ulcorner;
                varargout{1}(3:4)=lrcorner-ulcorner+1;
            else % Series of points
                for i=1:length(x)
                    varargout{1}(i, 1:2)=round(mitm_hand.axescoords2native([x(i) y(i)]));
                end
            end
            varargout{2}=mitm_hand.FrameSubFileIndices{mitm_hand.Frame}; % Which frame was AOI selected in?
            if isa(p.Results.selectCallback,'function_handle')
                try
                    p.Results.selectCallback(varargout{:});
                catch
                    delete(h); if exist('h2','var'), delete(h2); end;
                    rethrow(lasterror);
                end
                delete(h); if exist('h2','var'), delete(h2); end;
            else
                if (p.Results.closeAfterSelect)
                    close(fig_hand);
                else
                    set(uip_hand,'UserData','AOI_finished'); % If you want to keep window, do this
                    drawnow; % If you don't do this, everything freezes when you disable button
                    aoiButton.setEnabled(false);
                end
            end
        else
            delete(h); if exist('h2','var'), delete(h2); end;
        end
    end
end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


function [outputMovie, movieDims, nPixels, nFrames] = loadMovieList(movieList, varargin)
	% Load movies, automatically detects type (avi, tif, or hdf5) and concatenates if multiple movies in a list.
		% NOTE:
			% The function assumes input is 2D time series movies with [x y frames] as dimensions
			% If movies are different sizes, use largest dimensions and align all movies to top-left corner.
	% Biafra Ahanonu
	% started: 2013.11.01

	[outputMovie, movieDims, nPixels, nFrames] = ciapkg.io.loadMovieList(movieList, 'passArgs', varargin);
end


function view = initHiddenFlat(subdir)
%
%  hiddenFlat = initHiddenFlat([subdir])
%
% subdir: string specifying the flat subdirectory
%
% ras, 2004: made it
% ras, 04/05, set name to 'hidden'
% ras, 05/05, added curScan field
disp('Initializing HIDDEN Flat view')
% Set viewType
view.name='hidden';
view.viewType='Flat';
% Prompt user for flat subdirectory
if ~exist('subdir','var')
    subdir = getFlatSubdir;
end
view.subdir = subdir;
% Initialize slots for co, amp, and ph
view.co = [];
view.amp = [];
view.ph = [];
view.map = [];
view.mapName = '';
view.mapUnits = '';
% Initialize slots for tSeries
view.tSeries = [];
view.tSeriesScan = NaN;
view.tSeriesSlice = NaN;
% Initialize ROIs
view.ROIs = [];
view.selectedROI = 0;
% Initialize curDataType
view.curDataType = 1;
% Initialize curScan
view.curScan = 1;
% Compute/load coords
view = getFlatLevelCoords(view);
return;


function ClickToSelectOffense(patch, ~, game, player)

N = numel(game.board);

%% RESET ALL PATCHES TO NEUTRAL
for i = 1:N
    occupant = get(game.board(i).Patch, 'UserData');
    if occupant(1) == player
        set(game.board(i).Patch, 'UserData', [player, 0], ...
                                 'FaceColor', game.cmap(player, :));
        set(game.board(i).Text, 'Color', [0 0 0]);
    end
end

%% SET CURRRENT PATCH TO OFFENSE
idx = str2double(get(patch, 'Tag'));
set(game.board(idx).Patch, 'UserData', [player 1], ...
                           'FaceColor', game.cmap(7,:));
set(game.board(idx).Text, 'Color', game.cmap(8,:));


function blastStructure=getBlastFromExcel(models,blastFile,organismId)
% getBlastFromExcel
%   Retrieves gene homology information from Excel files. Used as
%   input to getModelFromHomology.
%
%   Input:
%   models          a cell array of model structures
%   blastFile       Excel file with homology information
%   organismId      the id of the organism of interest (as described in the
%                   Excel file)
%
%   Output:
%   blastStructure  structure containing the information in the Excel
%                   sheets.
%
%   The Excel file should contain a number of spreadsheets which in turn
%   contain the bidirectional homology measurements between the genes in the
%   organisms. The first and second column headers in each sheet is the
%   "to" and "from" model ids (as defined in models or for the new organism).
%   The entries should correspond to the gene names in those models. The third,
%   fourth, fifth, sixth and seventh columns represent the E-value, alignment
%   length, identity, bitscore and percentage of positive-scoring matches for
%   each measurement (captions should be "E-value", "Alignment length",
%   "Identity", "Bitscore" and "PPOS").
%
%   Usage: blastStructure=getBlastFromExcel(models,blastFile,organismId)

if ~isfile(blastFile)
    error('BLAST result file %s cannot be found',string(blastFile));
end
organismId=char(organismId);

blastStructure=[];

%Get a list of model IDs
organisms=cell(numel(models)+1,1);
organisms{1}=organismId;
for i=1:numel(models)
    organisms{i+1}=models{i}.id;
end

%Get all the spreadsheets in the file
[type, sheets]=xlsfinfo(blastFile);

%Check if the file is a Microsoft Excel Spreadsheet
if ~any(regexp(type,'Excel Spreadsheet'))
    EM='The file is not a Microsoft Excel Spreadsheet';
    dispEM(EM);
end

for i=1:numel(sheets)
    %Check if the sheet has the right header and deal with organisms that
    %are in "models"
    [values,dataSheet]=xlsread(blastFile,i);
    labels=dataSheet(1,:);
    if strcmpi(labels{3},'E-value') && strcmpi(labels{4},'Alignment length') ...
            && strcmpi(labels{5},'Identity') && strcmpi(labels{6},'Bitscore') ...
            && strcmpi(labels{7},'PPOS')
        %At least one of the organisms must have a model
        fromID=find(strcmpi(labels{1},organisms));
        toID=find(strcmpi(labels{2},organisms));
        %Check that the organism ids exist and that one of them is the
        %organism of interest
        if any(fromID) && any(toID) && (toID==1 || fromID==1)
            %Check that no gene ids are empty. This could for example be
            %the case if the gene names are wrongly formatted as numbers
            %instead of strings
            emptyNames=cellfun(@isempty,dataSheet(2:end,1)) | cellfun(@isempty,dataSheet(2:end,2));
            if any(emptyNames)
                if all(emptyNames)
                    EM=['Only empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID}];
                    dispEM(EM);
                else
                    EM=['Empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID} '. Ignoring genes with empty names'];
                    dispEM(EM,false);
                end
            end
            blastStructure(numel(blastStructure)+1).toId=organisms{toID};
            blastStructure(numel(blastStructure)).fromId=organisms{fromID};
            blastStructure(numel(blastStructure)).fromGenes=dataSheet(2:end,1);
            blastStructure(numel(blastStructure)).toGenes=dataSheet(2:end,2);
            blastStructure(numel(blastStructure)).evalue=values(:,1);
            blastStructure(numel(blastStructure)).aligLen=values(:,2);
            blastStructure(numel(blastStructure)).identity=values(:,3);
            blastStructure(numel(blastStructure)).bitscore=values(:,4);
            blastStructure(numel(blastStructure)).ppos=values(:,5);

            %Remove matches where any of the values is NaN. This would have
            %been done anyways in getModelFromHomology, but it's neater to
            %do it here
            I=isnan(blastStructure(end).evalue) | isnan(blastStructure(end).aligLen) | isnan(blastStructure(end).identity);
            blastStructure(end).fromGenes(I)=[];
            blastStructure(end).toGenes(I)=[];
            blastStructure(end).evalue(I)=[];
            blastStructure(end).aligLen(I)=[];
            blastStructure(end).identity(I)=[];
            blastStructure(end).bitscore(I)=[];
            blastStructure(end).ppos(I)=[];
        else
            if isempty(toID) || isempty(fromID)
                EM=['The data in sheet ' sheets{i} ' has no corresponding model. Ignoring sheet'];
                dispEM(EM,false);
            else
                EM=['The data in sheet ' sheets{i} ' does not involve the organism of interest. Ignoring sheet'];
                dispEM(EM,false);
            end
        end
    else
        EM=['The data in sheet ' sheets{i} ' is not correctly formatted. Ignoring sheet'];
        dispEM(EM,false);
    end
end

end


function fieldnameIndex = compileFieldnameIndex(matFiles)
% Traverse the extracts of all matfiles, compiling a list of all fields and
% indexing from fieldnames to the matfile num.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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 3 of the License, or
%     (at your option) any later version.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

disp('planDB>> Compiling fieldname Index...');
fieldnameIndex = struct('fieldname', {},'planIndices',{});
for i=1:length(matFiles)
    if matFiles(i).isPlanC
        newfieldnames = listAllFieldNames(matFiles(i).extract);
        oldfieldnames = [fieldnameIndex.fieldname]';
        [C, INew, IOld] = intersect(newfieldnames, oldfieldnames);

        for j=1:length(IOld)
            fieldnameIndex(IOld(j)).planIndices(end+1) = i;
        end

        if isempty(oldfieldnames)
            oldfieldnames={};
        end

        [C, INew] = setdiff(newfieldnames, oldfieldnames);

        for j=1:length(INew)
            fieldnameIndex(end+1).fieldname = newfieldnames(INew(j));
            fieldnameIndex(end).planIndices = i;
        end

    end
end

for i=1:length(fieldnameIndex)
    fieldnameIndex(i).fieldname = fieldnameIndex(i).fieldname{:};
end

disp('planDB>> Fieldname Index Complete.');


function ker = set_grid(ker, nthreads)

global data;

block_size = min(nthreads, 512);
grid_size = min([ceil(nthreads / block_size), 1], data.gpu.max_grid_size);
if any(ker.block_size ~= block_size) || any(ker.grid_size ~= grid_size)
    %gpu_sync();
    ker.block_size = block_size;
    ker.grid_size = grid_size;
    ker.ker.ThreadBlockSize = block_size;
    ker.ker.GridSize = grid_size;
    data.gpu.kernels.(ker.name) = ker;
end


function GUI = sessionGUI_selectROIType(type);
% Select the type of ROI to browse using the mrVista Session GUI.
%
% GUI = sessionGUI_selectROIType(<type name, or uicontrol handle>, <GUI>);
%
% Can provide the name or flag of an ROI type (described below), or else a
% handle to a uicontrol used to  select the ROI type.
%
% ROI types include:
%	'inplane', 1:	load an ROI from the local Inplane/ROIs directory.
%
%	'volume', 'volume shared', 'gray shared', 2: load an ROI from the
%	shared volume/gray directory. Usually this is 3DAnatomy/ROIs.
%
%	'gray local', 3: load an ROI from the local Gray/ROIs directory.
%
%	'volume local', 4: load an ROI from the local Volume/ROIs directory.
%
%	'browse', 'browse...', 5: browse for an ROI file. The ROI will be
%	assumed to be in the volume (I|P|R) coordinate system, and will be
%	aligned to the current data based on the saved transform into this
%	space.
%
%  All specifications are case-insensitive.
%
% If the handle to a uicontrol (popup) is provided, will select the
% session based on the currently-selected value of the uicontrol.
%
% If no argument is provided, will get from the GUI.controls.roiType
% listbox.
%
% The GUI input/output args do not generally need to be called, as this
% function will update the global variable GUI, as well as the mrGlobals
% variables. However, it will formally allow keeping this information in
% other, independent, structures.
%
% ras, 07/03/06.
mrGlobals2;

if notDefined('type'), type = GUI.controls.roiType; end

types = {'inplane' 'volume' 'gray local' 'volume local' 'browse...'};

% parse how the argument was passed
if ischar(type)
    type = cellfind(types, lower(type));
    if isempty(type)
        error('Invalid string value for ''type'' argument.')
    end

elseif isnumeric(type) & mod(type, 1)==0
    % ok as long as it's in [1-5]
    if (type < 1) | (type > 5)
        error('Invalid numeric value for type argument.')
    end

elseif ishandle(type)
    type = get(type, 'Value');

end

% update the ROI listbox to have a list of relevant ROIs for this type;
% select the first one by default:
switch type
	case {'inplane' 1}
		w = what( roiDir(INPLANE{1}) );

	case {'volume' 'volume shared' 'gray shared' 2}
		w = what( roiDir(VOLUME{1}, 0) );

	case {'gray local' 3}
		w = what( roiDir(VOLUME{1}, 1) );

	case {'volume local' 4}
		w = what( fullfile(HOMEDIR, 'Volume', 'ROIs') );

	case {'browse' 'browse...' 5}
		% for browsing, we ask the user to select the directory to browse
		% (but only if one hasn't already been selected)
		browseDir = get(GUI.controls.roiType, 'String');
		browseDir = browseDir{end};
		if strncmp( lower(browseDir), 'browse', 5 )
			txt = 'Select an ROI directory to browse';
			browseDir = uigetdir( fileparts(HOMEDIR), txt );
		end
		w = what(browseDir);

	otherwise
		error('Invalid ROI type.')
end

% if the user selected the 'browse' option, set the popup to reflect the
% browsing directory. Otherwise, reset the text to 'Browse...'.
str = get(GUI.controls.roiType, 'String');
if strncmp(type, 'browse', 5) | type==5
	str{end} = browseDir;
else
	str{end} = 'Browse...';
end
set(GUI.controls.roiType, 'String', str);

rois = {};
for i = 1:length(w.mat), [p rois{i} ext] = fileparts(w.mat{i}); end
rois = sort(rois);

set(GUI.controls.roi, 'String', rois, 'Value', 1);

% keep values in settings
GUI.settings.roiType = type;

return


function [model]  = setRxnSubSystems(model,reactions,subSystems)
% Sets the subSystems of the specified reactions to the specified
% subSystems
%
% USAGE:
%
%    [model]  = addSubSystemToReaction(model,reaction,subSystem)
%
% INPUT:
%    model:                 A COBRA model struct with at least rxns and
%                           subSystems fields
%    reactions:             Either a string identifying a reaction, or a
%                           cell array of strings identifying multiple
%                           reactions, or a double vector or boolean vector
%                           identifying positions.
%    subSystems:            A String identifying a subsystem, or a cell
%                           array of strings to assign multiple subSystems.
%                           If multiple strings are present, an empty
%                           string will be removed
%
% OUTPUT:
%    model:                 The model with the subSystems set to the
%                           respective reactions (old values will be removed).
%
% EXAMPLE:
%    % Set TCA as subSystem for a set of reactions
%    [model]  = setRxnSubSystems(model, {'ACONTa';'ACONTb';'AKGDH';'CS';'FUM';'ICDHyr';'MDH';'SUCOAS'}, 'TCA')
%    % Set Glycolysis/Gluconeogenesis to reaction 18 of the model
%    [model]  = setRxnSubSystems(model, 18, {'Glycolysis','Gluconeogenesis'})
%
% .. Author: - Thomas Pfau Nov 2017

if ischar(reactions) || iscell(reactions)
    [tempreactions] = ismember(model.rxns,reactions);
    if (iscell(reactions) && (sum(tempreactions) ~= length(reactions))) || (ischar(reactions) && sum(tempreactions) ~= 1)
        %If there are an unequal amount of reactions
        warning('There were reaction IDs not present in the model');
    end
    reactions = tempreactions;
end

if ~isfield(model,'subSystems')
    model.subSystems = cell(numel(model.rxns),1);
    model.subSystems(:) = {{''}};
end

if ischar(subSystems)
    subSystems = {subSystems};
end

if numel(subSystems) > 1
    subSystems = setdiff(subSystems,{''});
end

model.subSystems(reactions) = {subSystems};


function []= fill_legend(obj,title_text,legend_text,legend_type,legend_color,legend_marker,legend_linestyle,legend_line_size,legend_point_size)

legend_y_step=1;
legend_y_additional_step=0.5;

obj.legend_text_handles=[obj.legend_text_handles...
    text(1,obj.legend_y,title_text,...
    'FontWeight','bold',...
    'Interpreter',obj.text_options.interpreter,...
    'FontName',obj.text_options.font,...
    'FontSize',obj.text_options.base_size*obj.text_options.legend_title_scaling,...
    'Parent',obj.legend_axe_handle)];

obj.legend_y=obj.legend_y-legend_y_step;

for ind_legend=1:length(legend_text)

    if size(legend_color,1)>1
        temp_color = legend_color(ind_legend,:);
    else
        temp_color = legend_color;
    end

    if length(legend_marker)>1
        temp_marker = legend_marker{ind_legend};
    else
        temp_marker = legend_marker;
    end

    if length(legend_linestyle)>1
        temp_linestyle = legend_linestyle{ind_legend};
    else
        temp_linestyle = legend_linestyle;
    end

   if length(legend_line_size)>1
        temp_line_size = legend_line_size(ind_legend);
    else
        temp_line_size = legend_line_size;
   end

   if length(legend_point_size)>1
        temp_point_size = legend_point_size(ind_legend);
    else
        temp_point_size = legend_point_size;
    end

    if strcmp(legend_type,'point')
        plot(1.5,obj.legend_y,temp_marker,...
            'MarkerEdgeColor','none',...
            'MarkerFaceColor', temp_color,...
            'Parent',obj.legend_axe_handle,...
            'MarkerSize',temp_point_size);
    end
    if strcmp(legend_type,'line') || strcmp(legend_type,'both')
        plot([1 2],[obj.legend_y obj.legend_y],temp_linestyle,...
            'Color',temp_color,...
            'lineWidth',temp_line_size,...
            'Parent',obj.legend_axe_handle)
    end
    if strcmp(legend_type,'both')
        plot(1,obj.legend_y,temp_marker,...
            'MarkerEdgeColor','none',...
            'MarkerFaceColor', temp_color,...
            'Parent',obj.legend_axe_handle,...
            'MarkerSize',temp_point_size);
    end

    obj.legend_text_handles=[obj.legend_text_handles...
        text(2.5,obj.legend_y,legend_text{ind_legend},...
        'Interpreter',obj.text_options.interpreter,...
        'FontName',obj.text_options.font,...
        'FontSize',obj.text_options.base_size*obj.text_options.legend_scaling,...
        'Parent',obj.legend_axe_handle)];

    obj.legend_y=obj.legend_y-legend_y_step;
end

obj.legend_y=obj.legend_y-legend_y_additional_step;

end


function v = cvx_value( x )
v = value( x );

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function amd_install
%AMD_INSTALL compile and install amd2 for use in MATLAB
%   Your current directory must be AMD/MATLAB for this function to work.
%
% Example:
%   amd_install
%
% See also amd, amd2.

% Copyright 1994-2007, Tim Davis, Patrick R. Amestoy, and Iain S. Duff.

% This orders the same matrix as the ANSI C demo, amd_demo.c.  It includes an

amd_make
addpath (pwd)
fprintf ('\nThe following path has been added.  You may wish to add it\n') ;
fprintf ('permanently, using the MATLAB pathtool command.\n') ;
fprintf ('%s\n\n', pwd) ;
amd_demo


function varargout = Sim_Single_Voxel_Curve_GUI(varargin)
% SIM_SINGLE_VOXEL_CURVE_GUI MATLAB code for Sim_Single_Voxel_Curve_GUI.fig
%      SIM_SINGLE_VOXEL_CURVE_GUI, by itself, creates a new SIM_SINGLE_VOXEL_CURVE_GUI or raises the existing
%      singleton*.
%
%      H = SIM_SINGLE_VOXEL_CURVE_GUI returns the handle to a new SIM_SINGLE_VOXEL_CURVE_GUI or the handle to
%      the existing singleton*.
%
%      SIM_SINGLE_VOXEL_CURVE_GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in SIM_SINGLE_VOXEL_CURVE_GUI.M with the given input arguments.
%
%      SIM_SINGLE_VOXEL_CURVE_GUI('Property','Value',...) creates a new SIM_SINGLE_VOXEL_CURVE_GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before Sim_Single_Voxel_Curve_GUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to Sim_Single_Voxel_Curve_GUI_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 Sim_Single_Voxel_Curve_GUI

% Last Modified by GUIDE v2.5 10-Jul-2017 21:03:41

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

% --- Executes just before Sim_Single_Voxel_Curve_GUI is made visible.
function Sim_Single_Voxel_Curve_GUI_OpeningFcn(hObject, eventdata, handles, varargin)
set(findobj('Name','qMRLab'),'pointer', 'watch'); drawnow;

Model = varargin{1};
setappdata(0,'Model',Model);

if ~isfield(handles,'opened')
    handles.output = hObject;
    handles.Model = varargin{1};
    % OPTIONS
    if isprop(handles.Model,'Sim_Single_Voxel_Curve_buttons')
        opts = handles.Model.Sim_Single_Voxel_Curve_buttons;
    else
        opts = {'SNR',50};
    end

    % Generate Buttons
    handles.options = GenerateButtonsWithPanels(opts,handles.OptionsPanel);

     % Create CALLBACK for buttons
    ff = fieldnames(handles.options);
    for ii=1:length(ff)
        switch get(handles.options.(ff{ii}),'Style')
%             case 'popupmenu'
%                 val =  find(cell2mat(cellfun(@(x) strcmp(x,Model.options.(ff{ii})),get(handles.OptionsPanel_handle.(ff{ii}),'String'),'UniformOutput',0)));
%                 set(handles.OptionsPanel_handle.(ff{ii}),'Value',val);
%             case 'checkbox'
%                 set(handles.OptionsPanel_handle.(ff{ii}),'Value',Model.options.(ff{ii}));
%             case 'edit'
%                 set(handles.OptionsPanel_handle.(ff{ii}),'String',Model.options.(ff{ii}));
            case 'togglebutton'
                set(handles.options.(ff{ii}),'Callback',@(src,event) ModelSimOptions_Callback(handles));
        end
    end

    Nparam = length(handles.Model.xnames);
    FitOptTable(:,1)=handles.Model.xnames(:);
    if isprop(handles.Model,'st') && ~isempty(handles.Model.st)
        FitOptTable(:,2)=mat2cell(handles.Model.st(:),ones(Nparam,1));
    elseif isprop(handles.Model,'lb') && ~isempty(handles.Model.lb) && isprop(handles.Model,'ub') && ~isempty(handles.Model.ub)
        FitOptTable(:,2) = mat2cell(mean([handles.Model.lb(:), handles.Model.ub(:)],2),ones(Nparam,1));
    end
    set(handles.ParamTable,'Data',FitOptTable)

%     % launch plot
%     UpdatePlot_Callback(hObject, eventdata, handles)

    % opened
    handles.opened = true;
end
% Update handles structure
guidata(hObject, handles);
set(findobj('Name','qMRLab'),'pointer', 'arrow'); drawnow;

% --- Executes on button press in UpdatePlot.
function UpdatePlot_Callback(hObject, eventdata, handles)
Model_new = getappdata(0,'Model');
if ~isempty(Model_new) && strcmp(class(Model_new),class(handles.Model))
    handles.Model = Model_new;
end
set(findobj('Name','Single Voxel Curve'),'pointer', 'watch'); drawnow;
if isgraphics(handles.SimCurveAxe)
    axes(handles.SimCurveAxe)
end

xtable = get(handles.ParamTable,'Data');
x=cell2mat(xtable(~cellfun(@isempty,xtable(:,2)),2))';

FitResults = Sim_Single_Voxel_Curve(handles.Model,x,button_handle2opts(handles.options));
hold off;

% put results in table
ff = fieldnames(FitResults);
for ii=1:length(ff)
    index = strcmp(xtable(:,1),ff{ii});
    if find(index)
        xtable{index,3} = FitResults.(ff{ii})(1);
        xtable{index,4} = round((FitResults.(ff{ii})(1) - xtable{index,2})/xtable{index,2}*100);
    else
        xtable{end+1,1} = ff{ii};
        xtable{end,3} = FitResults.(ff{ii})(1);
    end
end

% CRLB
SNR = str2double(get(handles.options.SNR,'String'));
[~,~,~,F] = SimCRLB(handles.Model,handles.Model.Prot.(handles.Model.MRIinputs{1}).Mat,x,1/SNR);

for ii=1:sum(~handles.Model.fx)
    ll=find(~handles.Model.fx);
    xtable{ll(ii),5}=F(ii)*100;
end
set(handles.ParamTable,'Data',xtable);
set(findobj('Name','Single Voxel Curve'),'pointer', 'arrow'); drawnow;

% --- Executes on button press in Options panel.
function ModelSimOptions_Callback(handles)
xtable = get(handles.ParamTable,'Data');
x=cell2mat(xtable(~cellfun(@isempty,xtable(:,2)),2))';
xnew = SimOpt(handles.Model,x,button_handle2opts(handles.options));
if ~isempty(xnew) % update the ParamTable in the GUI
    Nparam = length(handles.Model.xnames);
    xtable(1:Nparam,2) = mat2cell(xnew',ones(Nparam,1));
    set(handles.ParamTable,'Data',xtable);
end

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


% Master m-file: seis_var.m
%
% Masterscript for the study of seismicity rate changes and variations
%
% Author: J. Woessner, woessner@seismo.ifg.ethz.ch
% last update: 26.06.02
%
basfig=figure_w_normalized_uicontrolunits('tag','welcomefig','Units','normalized','Position',[0.05 0.5 0.4 0.4],'Name','Detecting seismicity variations',...
    'NumberTitle','off');

% Buttons
seis_shift=uicontrol('Style', 'pushbutton', 'String', 'Magnitude characteristics','Units','normalized',...
    'Position',[0.1 0.10 0.3 0.06],'Callback','seisshift');
timestretch=uicontrol('Style', 'pushbutton', 'String', 'Time stretch a catalog','Units','normalized',...
    'Position',[0.1 0.80 0.3 0.06],'Callback','ftimestretch');
exit=uicontrol('Style', 'pushbutton', 'String', 'Exit','Units','normalized',...
    'Position',[0.7 0.1 0.15 0.06],'Callback','delete(findobj(''tag'',''welcomefig'')); close all');

% Figures
%topofig=figure_w_normalized_uicontrolunits('tag','Topography','Name','Topography plot','Nextplot','add','Units', 'normalized',...
%    'Position',[0.5 0.5 0.4 0.4],'Numbertitle','off');
%axtopofig=axes('tag','axtopo','NextPlot','add','box','on');


function cs_test_make (force)
%CS_TEST_MAKE compiles the CSparse, Demo, and Test mexFunctions.
%   The current directory must be CSparse/MATLAB/Test to use this function.
%
% Example:
%   cs_test_make
% See also: testall

%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

if (nargin < 1)
    force = 0 ;
end

cd ('../CSparse') ;
[object_files timestamp] = cs_make ;
cd ('../Test') ;

mexfunc = { 'cs_ipvec', 'cs_pvec', 'cs_sparse2', ...
    'cs_reach', 'cs_maxtransr', 'cs_reachr', 'cs_rowcnt', 'cs_frand' } ;

for i = 1:length(mexfunc)
    [s t tobj] = cs_must_compile ('', mexfunc{i}, '_mex', ...
        ['.' mexext], 'cs_test_make.m', force) ;
    if (s | tobj < timestamp)                                               %#ok
        cmd = ['mex -O -output ' mexfunc{i} ' ' mexfunc{i} '_mex.c -I..' ...
            filesep '..' filesep 'Include -I..' ...
            filesep 'CSparse ' object_files] ;
        fprintf ('%s\n', cmd) ;
        eval (cmd) ;
     end
end


% this is tha main screen of the program, which includes every aspect of our project you can see the help for further information

function menu()
fig=figure('name','Cellular Project','menubar','none','numbertitle','off','units','normalized','color','w',...
    'position',[0.25 0.25 0.7 0.65])
h1=axes('units','normalized','position',[.01 0.3 0.3 .47],'xcolor',[1 1 1],'ycolor',[1 1 1])
t1=uicontrol('style','text','units','normalized','position',[0.4 0.8 0.3 0.1],'fontname','arial','fontsize',10,'string','Please Click On One Of The Following')
a1=uicontrol('style','listbox','string',[{'Traffic Cacluation'},{'Site Configuration'},{'Report'},{'Close'}],'units','normalized','position',[0.4 0.4 0.3 0.3],'fontname','comicsansms','fontsize',10,'callback',@push);
m1=uimenu('label','extra');
m2=uimenu('label','about');

uimenu(m2,'label','about me','callback',@me);
uimenu(m1,'label','maximize','callback',@men);
uimenu(m1,'label','traffic','callback',@tra,'separator','on');
uimenu(m1,'label','cellular','callback',@cel,'separator','off');
uimenu(m1,'label','close','callback',@cls,'separator','on');
m3=uimenu('label','help','callback',@help)
   axis(h1);
   ss=imread('ju1.jpg');
   imshow(ss)
	function help(varargin)
		open('help.doc')
	end
	function me(varargin)
str=sprintf(['Sanad Amin \n\n',...
    'Reg No:0057035 \n',...
    'Sanad_amin@hotmail.com'])
msgbox(str,'About Me','help')
    end
    function men(varargin)

       set(fig,'units','normalized','position',[0.01 0.01 1 0.95]) ;
    end
    function tra(varargin)
       run traffic
    end
    function cel(varargin)
       run cellular
    end
    function cls(varargin)
        close(gcf)

    end
    function push(varargin)
       val=get(a1,'value');
       if val==1;
         run traffic
       else if val==2;
               run cellular
		   else if val==3
				   open('report.doc')
			   end
		    if val==4;
                  close(gcf) ;
               end

           end
       end
    end

end


function save_as_pdf(plot_obj,outfilename)
% Saves the plot to a PDF file.
% Inputs:
%   outfilename: The name of the PDF file in which the plot will be
%     saved.

assert(ischar(outfilename))
saveas(plot_obj.fh,outfilename,'pdf');
end


function planC_for_XNAT(dicomPath,cerrPath,xhost,xproj,xsubj,xexp, rebuildRS)
% function planC_for_XNAT(dicomPath,cerrPath,xhost,xproj,xsubj,xexp,rebuildRS)
%
% This function imports DICOM files from dicomPath and adds header info
% with XNAT addressing metadata

if ~exist('rebuildRS','var')
    rebuildRS = 0;
end

if strcmpi(rebuildRS,'Y')
    rebuildRS = 1;
end

disp(['importing DICOM from ' dicomPath]);
initFlag = init_ML_DICOM;
importDICOM(dicomPath,cerrPath);

C = dir(fullfile(cerrPath, '*.mat'));
cerrFile = fullfile(C.folder, C.name);

planC = loadPlanC(cerrFile);

planC = annotatePlanCForXNAT(planC, xhost,xexp,xproj,xsubj);

strE = strsplit(xexp,'E');
numExt = str2num(strE{end});

if rebuildRS
    planC = reviveRS(planC,cerrPath,numExt);
end

save_planC(planC,[],'passed',cerrFile);


function move(obj, device)
%MOVE Move the DagNN to either CPU or GPU
%   MOVE(obj, 'cpu') moves the DagNN obj to the CPU.
%
%   MOVE(obj, 'gpu') moves the DagNN obj to the GPU.

% Copyright (C) 2015 Karel Lenc and Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

obj.reset() ;
obj.device = device ;
switch device
  case 'gpu'
    for i=1:numel(obj.params)
      obj.params(i).value = gpuArray(obj.params(i).value) ;
    end
  case 'cpu'
    for i=1:numel(obj.params)
      obj.params(i).value = gather(obj.params(i).value) ;
    end
  otherwise
    error('DEVICE must be either ''cpu'' or ''gpu''.') ;
end
for l = 1:numel(obj.layers)
  obj.layers(l).block.move(device) ;
end


function result = combine_structs(args,structmask)
% Turn a list of name-value pairs/structs into a single struct.
% Struct = combine_structs(Arguments,StructMask)
%
% In:
%   Arguments : cell array of function arguments in form of name-value pairs, possibly interleaved
%               with structs {'name',value,STRUCT,'name',value,'name',value, ...}
%
%   StructMask : a bitmask that encodes at what positions Arguments contains structs; optional.
%
% Out:
%   Struct : A struct with values assigned to fields
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2013-11-03

if nargin < 2
    structmask = cellfun('isclass',args,'struct'); end

if isscalar(structmask)
    % inputs has already a single struct
    result = args{1};
else
    % obtain flat NVP list
    nvps = flatten_structs(args,structmask);
    % split names/values and find indices of the last assignment for each name
    nvps = reshape(nvps,2,[]);
    [s,indices] = sort(nvps(1,:));
    indices(strcmp(s(1:end-1),s(2:end))) = [];
    % build the struct
    result = cell2struct(nvps(2,indices),nvps(1,indices),2);
end


function [states] = tapas_sem_multiv_init_states(data, model, inference)
%% Generates the data structure to store the samples.
%
% Input
%
%
% Output
%   data        -- Cell array with nx1 cells, where n = niter
%

% aponteeduardo@gmail.com
% copyright (C) 2016
%

states = cell(inference.niter, 1);

end


function figh=hlp_viewGraphicsResource(rscName,hax)
% render a SIFT graphical resource (.jpg, .png, ...) in a figure
% Inputs:
%   rscName:    relative path and name of resource. Path is relative to
%               <sift-root>/resources
%   hax:        optional axis in which to plot image
%
%
% Author: Tim Mullen 2013, SCCN/INC, UCSD.
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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 3 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

if nargin<2 || isempty(ax)
    hax = [];
end
if isempty(rscName)
    return; end
% remove leading/trailing whitespace
rscName = strtrim(rscName);
if ispc
    strrep(rscName,'/','\');
else
    strrep(rscName,'\','/');
end
% remove any leading slash
if strcmp(rscName(1),filesep)
    rscName(1) = []; end
% get sift rootpath
siftroot = fileparts(utl_whichfile('StartSift.m'));
% construct resource path
rscPath = [siftroot filesep 'resources' filesep rscName];
% check that file exists
if ~exist(rscPath,'file')
    error('SIFT:hlp_viewGraphicsResource:badResourcePath','Resource [%s] does not exist',rscPath);
end
[pathstr name ext] = fileparts(rscPath);
% display resource in figure
im = imread(rscPath);
if isempty(im)
    error('SIFT:hlp_viewGraphicsResource:badResource','Resource [%s] cannot be loaded',rscPath);
end
if isempty(hax)
    figh=figure('Name',[name ext]);
    hax=axes('parent',figh,'position',[0.01 0.01 0.98 0.98]);
end
% render the graphic
image(im,'parent',hax);
axis(hax,'off');
axis(hax,'image');


function acclaimPlayFile(fileNameAsf, fileNameAmc, frameLength)

% ACCLAIMPLAYFILE Play motion capture data from a asf and amc file.
% FORMAT
% DESC plays motion capture data by reading in a asf and amc files from disk.
% ARG fileNameAsf : the name of the ASF file to read in.
% ARG fileNameAmc : the name of the AMC file to read in.
% ARG frameLength : the length of the frames.
%
% COPYRIGHT : Neil D. Lawrence, 2006
%
% SEEALSO : acclaimPlayFile, bvhReadFile, skelPlayData

% MOCAP

skel = acclaimReadSkel(fileNameAsf);
[channels, skel] = acclaimLoadChannels(fileNameAmc, skel);
skelPlayData(skel, channels, frameLength);


function show_sites(sites)
                 for ccc=1:numel(sites)
                     debug.print_debug(1,sites(ccc).channeltag.string())
                 end
end


%  INTERNAL FUNCTION: different kernel densities
%
%


%
% FILE NAME:    mergeGlutamateSubsystem.m
%
% PURPOSE: Currently, there is only one reaction in the "Glutamate
%          metabolism" subsystem. The subsystem for this reaction will be
%          changed to "Alanine, aspartate and glutamate metabolism", which
%          contains 39 reactions.
%

% load model
load('humanGEM.mat');

% convert subsystems to cell array
subSystems = cellfun(@(x) x, ihuman.subSystems);

% find reaction in Glutamate metabolism subsystem
rxnInd = ismember(subSystems,'Glutamate metabolism');

% change subsystem to Alanine, aspartate and glutamate metabolism
ihuman.subSystems{rxnInd} = {'Alanine, aspartate and glutamate metabolism'};

% export model
exportHumanGEM(ihuman,'humanGEM','../../',{'mat','yml'},false,false);


function data = h5load(filename, path)
%
% data = H5LOAD(filename)
% data = H5LOAD(filename, path_in_file)
%
% Load data in a HDF5 file to a Matlab structure.
%
% Parameters
% ----------
%
% filename
%     Name of the file to load data from
% path_in_file : optional
%     Path to the part of the HDF5 file to load
%

% Author: Pauli Virtanen <pav@iki.fi>
% This script is in the Public Domain. No warranty.

if nargin > 1
    path_parts = regexp(path, '/', 'split');
else
    path = '';
    path_parts = [];
end

loc = H5F.open(filename, 'H5F_ACC_RDONLY', 'H5P_DEFAULT');
try
    data = load_one(loc, path_parts, path);
    H5F.close(loc);
catch exc
    H5F.close(loc);
    rethrow(exc);
end

% ---------------------------------------------------------------------
function data = load_one(loc, path_parts, full_path)
% Load a record recursively.

while ~isempty(path_parts) & strcmp(path_parts{1}, '')
    path_parts = path_parts(2:end);
end

data = struct();

num_objs = H5G.get_num_objs(loc);

%
% Load groups and datasets
%
for j_item = 0:num_objs-1
    objtype = H5G.get_objtype_by_idx(loc, j_item);
    objname = H5G.get_objname_by_idx(loc, j_item);

    if objtype == 0
        % Group
        name = regexprep(objname, '.*/', '');

        if isempty(path_parts) | strcmp(path_parts{1}, name)
            if ~isempty(regexp(name,'^[a-zA-Z].*'))
                try
                    group_loc = H5G.open(loc, name);
                catch
                    d=1;
                end
                try
                    sub_data = load_one(group_loc, path_parts(2:end), full_path);
                    H5G.close(group_loc);
                catch exc
                    H5G.close(group_loc);
                    rethrow(exc);
                end
                if isempty(path_parts)
                    data = setfield(data, name, sub_data);
                else
                    data = sub_data;
                    return
                end
            end
        end

    elseif objtype == 1
        % Dataset
        name = regexprep(objname, '.*/', '');

        if isempty(path_parts) | strcmp(path_parts{1}, name)
            if ~isempty(regexp(name,'^[a-zA-Z].*'))
                dataset_loc = H5D.open(loc, name);
                try
                    sub_data = H5D.read(dataset_loc, 'H5ML_DEFAULT', 'H5S_ALL','H5S_ALL','H5P_DEFAULT');
                    H5D.close(dataset_loc);
                catch exc
                    H5D.close(dataset_loc);
                    rethrow(exc);
                end

                sub_data = fix_data(sub_data);

                if isempty(path_parts)
                    data = setfield(data, name, sub_data);
                else
                    data = sub_data;
                    return
                end
            end
        end
    end
end

% Check that we managed to load something if path walking is in progress
if ~isempty(path_parts)
    error(sprintf('Path "%s" not found in the HDF5 file', full_path));
end

% ---------------------------------------------------------------------
function data = fix_data(data)
% Fix some common types of data to more friendly form.

if isstruct(data)
    fields = fieldnames(data);
    if length(fields) == 2 & strcmp(fields{1}, 'r') & strcmp(fields{2}, 'i')
        if isnumeric(data.r) & isnumeric(data.i)
            data = data.r + 1j*data.i;
        end
    end
end

if isnumeric(data) & ndims(data) > 1
    % permute dimensions
    data = permute(data, fliplr(1:ndims(data)));
end


classdef Dynamics < handle

% Copyright (C) 2013, Georgia Tech Research Corporation
% see the LICENSE file included with this software

    properties

    end

    methods
        function pose_t_1 = apply_dynamics(obj, pose_t, dt)

	end
    end

end


function [RefinedReactionsCarryingFlux, BlockedRefinedReactions] = testRefinedReactions(microbeID, BlockedRxns)
% Tests if reactions that were added through the refinement of gene
% annotations in the reconstructed organism can carry flux.
%
% INPUT
% microbeID         Microbe ID in data file with refined genome annotations
% BlockedRxns       Reactions in the COBRA model that cannot carry flux:
%                   output of identifyBlockedRxns function
%
% OUTPUT
% RefinedReactionsCarryingFlux     Reactions that were added through
%                                  refinement of the genome annotations
%                                  and can carry flux
%
% BlockedRefinedReactions          Reactions that were added through
%                                  refinement of the genome annotations
%                                  and cannot carry flux
%
%
% Almut Heinken, Nov 2019

BlockedRefinedReactions = {};
RefinedReactionsCarryingFlux = {};

if isfile('gapfilledGenomeAnnotation.txt')

    genomeAnnotation = readtable('gapfilledGenomeAnnotation.txt', 'ReadVariableNames', false, 'Delimiter', 'tab','TreatAsEmpty',['UND. -60001','UND. -2011','UND. -62011']);
    genomeAnnotation = table2cell(genomeAnnotation);

    % get the reactions that were added for the reconstruction
    findRxns=find(strcmp(microbeID,genomeAnnotation(:,1)));
    if ~isempty(findRxns)
        annRxns(:,1)=genomeAnnotation(findRxns(:,1),2);

        % find the overlap with blocked reactions in the model
        BlockedRefinedReactions = intersect(annRxns(:,1),BlockedRxns);
        RefinedReactionsCarryingFlux = setdiff(annRxns(:,1),BlockedRxns);
    end

end

end


% Defines a transcription unit
%
% Author: Jonathan Karr
% Affilitation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 5/7/2009
classdef TranscriptionUnit < edu.stanford.covert.cell.kb.ssRNA
    properties
        genome           = edu.stanford.covert.cell.kb.Genome.empty(0,0);

        genes            = edu.stanford.covert.cell.kb.Gene.empty(0,0);
        geneCompartments = edu.stanford.covert.cell.kb.Compartment.empty(0,0);

        compartment      = edu.stanford.covert.cell.kb.Compartment.empty(0,0);

        transcriptionFactorProteinMonomers            = edu.stanford.covert.cell.kb.ProteinMonomer.empty(0,0);
        transcriptionFactorProteinMonomerAffinitys    = []; %nM
        transcriptionFactorProteinMonomerActivitys    = [];
        transcriptionFactorProteinMonomerConditions   = [];
        transcriptionFactorProteinMonomerBindingSiteStartCoordinates = [];
        transcriptionFactorProteinMonomerBindingSiteLengths          = [];
        transcriptionFactorProteinMonomerBindingSiteDirections       = [];
        transcriptionFactorProteinMonomerCompartments = edu.stanford.covert.cell.kb.Compartment.empty(0,0);

        transcriptionFactorProteinComplexs            = edu.stanford.covert.cell.kb.ProteinComplex.empty(0,0);
        transcriptionFactorProteinComplexAffinitys    = []; %nM
        transcriptionFactorProteinComplexActivitys    = [];
        transcriptionFactorProteinComplexConditions   = [];
        transcriptionFactorProteinComplexBindingSiteStartCoordinates = [];
        transcriptionFactorProteinComplexBindingSiteLengths          = [];
        transcriptionFactorProteinComplexBindingSiteDirections       = [];
        transcriptionFactorProteinComplexCompartments = edu.stanford.covert.cell.kb.Compartment.empty(0,0);
    end

    properties %(SetAccess = protected)
        halfLife
        sequence
        promoter35Coordinate
        promoter35Length
        promoter10Coordinate
        promoter10Length
        tssCoordinate
    end

    %computed properties
    properties %(SetAccess = protected)
        type
        dnaSequence
        startCoordinate
        endCoordinate
        fivePrimeCoordinate
        threePrimeCoordinate
        direction
        synthesisRate
        expression

        promoter1Sequence
        promoter10Sequence
        promoter35Sequence

        intergenicSequences
        intergenicSequenceLengths
        intergenicSequenceBaseCounts
        intergenicSequenceDecayReactions
        intergenicSequenceMolecularWeights
        intergenicSequenceHalfLives

        numGenes
        features
    end

    methods
        function this = TranscriptionUnit(knowledgeBase, wid,wholeCellModelID,name,...
                promoter35Coordinate, promoter35Length, ...
                promoter10Coordinate, promoter10Length, ...
                tssCoordinate, ...
                comments,crossReferences)

            if nargin == 0; return; end;

            this = edu.stanford.covert.cell.kb.TranscriptionUnit.empty(size(wid,1),0);
            this(size(wid,1),1) = edu.stanford.covert.cell.kb.TranscriptionUnit;
            for i = 1:size(wid,1)
                this(i,1).idx = i;
                this(i,1).knowledgeBase = knowledgeBase;
                this(i,1).wid = wid(i);
                this(i,1).wholeCellModelID = wholeCellModelID{i};
                this(i,1).name = name{i};
                if exist('comments','var') && ~isempty(comments); this(i,1).comments = comments{i}; end;
                if exist('crossReferences','var')
                    if size(crossReferences,1)>1
                        this(i,1).crossReferences = crossReferences(i);
                    else
                        this(i,1).crossReferences = struct;
                        fields = fieldnames(crossReferences);
                        for j = 1:size(fields,1)
                            values = crossReferences.(fields{j});
                            this(i,1).crossReferences.(fields{j}) = values(i);
                        end
                    end
                end

                this(i,1).promoter35Coordinate = promoter35Coordinate(i);
                this(i,1).promoter35Length     = promoter35Length(i);
                this(i,1).promoter10Coordinate = promoter10Coordinate(i);
                this(i,1).promoter10Length     = promoter10Length(i);
                this(i,1).tssCoordinate        = tssCoordinate(i);
            end
        end

        function serializeLinks(this)
            for i = 1:numel(this)
                this(i).genome                                        = this.serializeLinksHelper(this(i).genome);

                this(i).genes                                         = this.serializeLinksHelper(this(i).genes);
                this(i).geneCompartments                              = this.serializeLinksHelper(this(i).geneCompartments);

                this(i).compartment                                   = this.serializeLinksHelper(this(i).compartment);

                this(i).transcriptionFactorProteinMonomers            = this.serializeLinksHelper(this(i).transcriptionFactorProteinMonomers);
                this(i).transcriptionFactorProteinMonomerAffinitys    = this.serializeLinksHelper(this(i).transcriptionFactorProteinMonomerAffinitys);
                this(i).transcriptionFactorProteinMonomerActivitys    = this.serializeLinksHelper(this(i).transcriptionFactorProteinMonomerActivitys);
                this(i).transcriptionFactorProteinMonomerConditions   = this.serializeLinksHelper(this(i).transcriptionFactorProteinMonomerConditions);
                this(i).transcriptionFactorProteinMonomerCompartments = this.serializeLinksHelper(this(i).transcriptionFactorProteinMonomerCompartments);

                this(i).transcriptionFactorProteinComplexs            = this.serializeLinksHelper(this(i).transcriptionFactorProteinComplexs);
                this(i).transcriptionFactorProteinComplexAffinitys    = this.serializeLinksHelper(this(i).transcriptionFactorProteinComplexAffinitys);
                this(i).transcriptionFactorProteinComplexActivitys    = this.serializeLinksHelper(this(i).transcriptionFactorProteinComplexActivitys);
                this(i).transcriptionFactorProteinComplexConditions   = this.serializeLinksHelper(this(i).transcriptionFactorProteinComplexConditions);
                this(i).transcriptionFactorProteinComplexCompartments = this.serializeLinksHelper(this(i).transcriptionFactorProteinComplexCompartments);

                serializeLinks@edu.stanford.covert.cell.kb.ssRNA(this(i));
            end
        end

        function deserializeLinks(this, kb)
            for i = 1:numel(this)
                this(i).genome                                        = this.deserializeLinksHelper(this(i).genome, kb.genome);

                this(i).genes                                         = this.deserializeLinksHelper(this(i).genes, kb.genes);
                this(i).geneCompartments                              = this.deserializeLinksHelper(this(i).geneCompartments, kb.compartments);

                this(i).compartment                                   = this.deserializeLinksHelper(this(i).compartment, kb.compartments);

                this(i).transcriptionFactorProteinMonomers            = this.deserializeLinksHelper(this(i).transcriptionFactorProteinMonomers, kb.proteinMonomers);
                this(i).transcriptionFactorProteinMonomerAffinitys    = this.deserializeLinksHelper(this(i).transcriptionFactorProteinMonomerAffinitys);
                this(i).transcriptionFactorProteinMonomerActivitys    = this.deserializeLinksHelper(this(i).transcriptionFactorProteinMonomerActivitys);
                this(i).transcriptionFactorProteinMonomerConditions   = this.deserializeLinksHelper(this(i).transcriptionFactorProteinMonomerConditions);
                this(i).transcriptionFactorProteinMonomerCompartments = this.deserializeLinksHelper(this(i).transcriptionFactorProteinMonomerCompartments, kb.compartments);

                this(i).transcriptionFactorProteinComplexs            = this.deserializeLinksHelper(this(i).transcriptionFactorProteinComplexs, kb.proteinComplexs);
                this(i).transcriptionFactorProteinComplexAffinitys    = this.deserializeLinksHelper(this(i).transcriptionFactorProteinComplexAffinitys);
                this(i).transcriptionFactorProteinComplexActivitys    = this.deserializeLinksHelper(this(i).transcriptionFactorProteinComplexActivitys);
                this(i).transcriptionFactorProteinComplexConditions   = this.deserializeLinksHelper(this(i).transcriptionFactorProteinComplexConditions);
                this(i).transcriptionFactorProteinComplexCompartments = this.deserializeLinksHelper(this(i).transcriptionFactorProteinComplexCompartments, kb.compartments);

                deserializeLinks@edu.stanford.covert.cell.kb.ssRNA(this(i), kb);
            end
        end

        function deleteLinks(this)
            for i = 1:numel(this)
                this(i).genome                                        = [];

                this(i).genes                                         = [];
                this(i).geneCompartments                              = [];

                this(i).compartment                                   = [];

                this(i).transcriptionFactorProteinMonomers            = [];
                this(i).transcriptionFactorProteinMonomerAffinitys    = [];
                this(i).transcriptionFactorProteinMonomerActivitys    = [];
                this(i).transcriptionFactorProteinMonomerConditions   = [];
                this(i).transcriptionFactorProteinMonomerCompartments = [];

                this(i).transcriptionFactorProteinComplexs            = [];
                this(i).transcriptionFactorProteinComplexAffinitys    = [];
                this(i).transcriptionFactorProteinComplexActivitys    = [];
                this(i).transcriptionFactorProteinComplexConditions   = [];
                this(i).transcriptionFactorProteinComplexCompartments = [];

                deleteLinks@edu.stanford.covert.cell.kb.ssRNA(this(i));
            end
        end

        function value = get.halfLife(this)
            %retrieve
            if ~isempty(this.halfLife)
                value = this.halfLife;
                return;
            end

            %compute
            value = mean([this.genes.halfLife]);

            %store
            this.halfLife = value;
        end

        function value = get.type(this)
            %retrieve
            if ~isempty(this.type)
                value = this.type;
                return;
            end

            %compute
            if ~isempty(this.genes)
                value = this.genes(1).type;
            else
                value = [];
            end

            %store
            this.type = value;
        end

        function value = get.dnaSequence(this)
            %retrieve
            if ~isempty(this.dnaSequence)
                value = this.dnaSequence;
                return;
            end

            %compute
            if this.direction
                value = this.genome.sequence(this.startCoordinate:this.endCoordinate);
            else
                value = seqrcomplement(this.genome.sequence(this.startCoordinate:this.endCoordinate));
            end

            %store
            this.dnaSequence = value;
        end

        function value = get.sequence(this)
            %retrieve
            if ~isempty(this.sequence)
                value = this.sequence;
                return;
            end

            %compute
            value = this.dnaSequence;
            value(this.dnaSequence == 'A') = 'U';
            value(this.dnaSequence == 'C') = 'G';
            value(this.dnaSequence == 'G') = 'C';
            value(this.dnaSequence == 'T') = 'A';

            %store
            this.sequence = value;
        end

        function value = get.startCoordinate(this)
            %retrieve
            if ~isempty(this.startCoordinate)
                value = this.startCoordinate;
                return;
            end

            %compute
            value = min([this.genes.startCoordinate]);

            %store
            this.startCoordinate = value;
        end

        function value = get.endCoordinate(this)
            %retrieve
            if ~isempty(this.endCoordinate)
                value = this.endCoordinate;
                return;
            end

            %compute
            value = max([this.genes.endCoordinate]);

            %store
            this.endCoordinate = value;
        end

        function value = get.fivePrimeCoordinate(this)
            %retrieve
            if ~isempty(this.fivePrimeCoordinate)
                value = this.fivePrimeCoordinate;
                return;
            end

            %compute
            if this.direction
                value = this.startCoordinate;
            else
                value = this.endCoordinate;
            end

            %store
            this.fivePrimeCoordinate = value;
        end

        function value = get.threePrimeCoordinate(this)
            %retrieve
            if ~isempty(this.threePrimeCoordinate)
                value = this.threePrimeCoordinate;
                return;
            end

            %compute
            if this.direction
                value = this.endCoordinate;
            else
                value = this.startCoordinate;
            end

            %store
            this.threePrimeCoordinate = value;
        end

        function value = get.direction(this)
            %retrieve
            if ~isempty(this.direction)
                value = this.direction;
                return;
            end

            %compute
            value = this.genes(1).direction;

            %store
            this.direction = value;
        end

        function value = get.synthesisRate(this)
            %retrieve
            if ~isempty(this.synthesisRate)
                value = this.synthesisRate;
                return;
            end

            %compute
            value = mean(reshape([this.genes.synthesisRate],[],this.numGenes),2)';

            %store
            this.synthesisRate = value;
        end

        function value = get.expression(this)
            %retrieve
            if ~isempty(this.expression)
                value = this.expression;
                return;
            end

            %compute
            value = this.synthesisRate*this.halfLife/log(2);

            %store
            this.expression = value;
        end

        function value = get.promoter1Sequence(this)
            %retrieve
            if ~isempty(this.promoter1Sequence)
                value = this.promoter1Sequence;
                return;
            end

            %compute
            if this.direction
                value = this.genome.sequence(this.fivePrimeCoordinate + this.tssCoordinate + (-1:-1) + 1);
            else
                value = seqcomplement(this.genome.sequence(this.fivePrimeCoordinate - this.tssCoordinate + (1:-1:1) - 1));
            end

            %store
            this.promoter1Sequence = value;
        end

        function value = get.promoter10Sequence(this)
            %retrieve
            if ~isempty(this.promoter10Sequence)
                value = this.promoter10Sequence;
                return;
            end

            %compute
            if this.direction
                value = this.genome.sequence(this.fivePrimeCoordinate + this.promoter10Coordinate + (-this.promoter10Length:-1) + 1);
            else
                value = seqcomplement(this.genome.sequence(this.fivePrimeCoordinate - this.promoter10Coordinate + (this.promoter10Length:-1:1) - 1));
            end

            %store
            this.promoter10Sequence = value;
        end

        function value = get.promoter35Sequence(this)
            %retrieve
            if ~isempty(this.promoter35Sequence)
                value = this.promoter35Sequence;
                return;
            end

            %compute
            if this.direction
                value = this.genome.sequence(this.fivePrimeCoordinate + this.promoter35Coordinate + (-this.promoter35Length:-1) + 1);
            else
                value = seqcomplement(this.genome.sequence(this.fivePrimeCoordinate - this.promoter35Coordinate + (this.promoter35Length:-1:1) - 1));
            end

            %store
            this.promoter35Sequence = value;
        end

        function value = get.intergenicSequences(this)
            %retrieve
            if ~isempty(this.intergenicSequences)
                value = this.intergenicSequences;
                return;
            end

            %compute
            value = cell(0,1);
            for i = 1:numel(this.genes)-1
                if strcmp(this.type,'mRNA')
                    continue;
                end
                if this.genes(i).endCoordinate+1 > this.genes(i+1).startCoordinate-1
                    continue;
                end

                if this.direction
                    seq = this.genome.sequence(this.genes(i).endCoordinate+1:this.genes(i+1).startCoordinate-1);
                else
                    seq = seqrcomplement(this.genome.sequence(this.genes(i).endCoordinate+1:this.genes(i+1).startCoordinate-1));
                end

                value{i,1} = seq;
                value{i,1}(seq == 'A') = 'U';
                value{i,1}(seq == 'C') = 'G';
                value{i,1}(seq == 'G') = 'C';
                value{i,1}(seq == 'T') = 'A';
            end

            %store
            this.intergenicSequences = value;
        end

        function value = get.intergenicSequenceLengths(this)
            %retrieve
            if ~isempty(this.intergenicSequenceLengths)
                value = this.intergenicSequenceLengths;
                return;
            end

            %compute
            value = zeros(0,1);
            for i = 1:numel(this.genes)-1
                if strcmp(this.type,'mRNA')
                    continue;
                end
                if this.genes(i).endCoordinate+1 > this.genes(i+1).startCoordinate-1
                    continue;
                end

                value(i,1) = (this.genes(i+1).startCoordinate-1) - (this.genes(i).endCoordinate+1) + 1;
            end

            %store
            this.intergenicSequenceLengths = value;
        end

        function value = get.intergenicSequenceBaseCounts(this)
            %retrieve
            if ~isempty(this.intergenicSequenceBaseCounts)
                value = this.intergenicSequenceBaseCounts;
                return;
            end

            %compute
            value = zeros(numel(this.intergenicSequences), this.knowledgeBase.numMetabolites);

            for i = 1:numel(this.intergenicSequences)
                value(i, this.knowledgeBase.nmpIndexs) = [...
                    sum('A' == this.intergenicSequences{i}) ...
                    sum('C' == this.intergenicSequences{i}) ...
                    sum('G' == this.intergenicSequences{i}) ...
                    sum('U' == this.intergenicSequences{i})];
            end

            %store
            this.intergenicSequenceBaseCounts = value;
        end

        function value = get.intergenicSequenceDecayReactions(this)
            %retrieve
            if ~isempty(this.intergenicSequenceDecayReactions)
                value = this.intergenicSequenceDecayReactions;
                return;
            end

            %compute
            value = this.intergenicSequenceBaseCounts;
            for i = 1:numel(this.intergenicSequences)
                value(i, this.knowledgeBase.waterIndexs)    = value(i, this.knowledgeBase.waterIndexs)    - max(0, length(this.intergenicSequences{i}) - 1);
                value(i, this.knowledgeBase.hydrogenIndexs) = value(i, this.knowledgeBase.hydrogenIndexs) + max(0, length(this.intergenicSequences{i}) - 1);
            end

            %store
            this.intergenicSequenceDecayReactions = value;
        end

        function value = get.intergenicSequenceMolecularWeights(this)
            %retrieve
            if ~isempty(this.intergenicSequenceMolecularWeights)
                value = this.intergenicSequenceMolecularWeights;
                return;
            end

            %compute
            value = zeros(size(this.intergenicSequences));

            for i = 1:numel(this.intergenicSequences)
                value(i) = this.calculateMolecularWeight(...
                    this.intergenicSequences{i}, length(this.intergenicSequences{i}), 'linear', ...
                    this.knowledgeBase.metaboliteMolecularWeights(this.knowledgeBase.nmpIndexs));
            end

            %store
            this.intergenicSequenceMolecularWeights = value;
        end

        function value = get.intergenicSequenceHalfLives(this)
            %retrieve
            if ~isempty(this.intergenicSequenceHalfLives)
                value = this.intergenicSequenceHalfLives;
                return;
            end

            %compute
            value = zeros(size(this.intergenicSequences));

            %store
            this.intergenicSequenceHalfLives = value;
        end

        function value = get.numGenes(this)
            %retrieve
            if ~isempty(this.numGenes)
                value = this.numGenes;
                return;
            end

            %compute
            value = length(this.genes);

            %store
            this.numGenes = value;
        end

        function value = get.features(this)
            %retrieve
            if ~isempty(this.features)
                value = this.features;
                return;
            end

            %compute
            featureStartCoordinates = [this.genome.features.startCoordinate];
            featureEndCoordinates = [this.genome.features.endCoordinate];
            value = this.genome.features(...
                (this.startCoordinate > featureStartCoordinates & this.startCoordinate < featureEndCoordinates) | ...
                (this.endCoordinate   > featureStartCoordinates & this.endCoordinate   < featureEndCoordinates) | ...
                (this.startCoordinate < featureStartCoordinates & this.endCoordinate   > featureEndCoordinates));

            %store
            this.features = value;
        end
    end
end