{"action":"created","comment":{"url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/comments/117042199","pull_request_review_id":38712836,"id":117042199,"diff_hunk":"@@ -0,0 +1,1099 @@\n+function tissueModel = call_mCADRE(model, gene_names, gene_exp, GPRmat, GPRrxns, core, threshold_high, checkv, eta, tol)\r\n+%Use the mCADRE algorithm (Wang et al., 2012*) to extract a context\r\n+%specific model using data. mCADRE algorithm defines a set of core\r\n+%reactions and prunes all other reactions based on their expression,\r\n+%connectivity to core and confidence score. The removal of reactions is not\r\n+%necessary performed to support the core of defined functionalities. Core\r\n+%reactions are only removed if supported by a certain number of\r\n+%zero-expression reactions.\r\n+%\r\n+%INPUTS\r\n+%\r\n+%   model               input model (COBRA model structure)\r\n+%   gene_names          gene identifiers corresponding to gene_exp\r\n+%                       (\"findUsedGeneLevels.m\")\r\n+%   gene_exp            gene expression corresponding to gene_id\r\n+%                       (\"findUsedGeneLevels.m\")\r\n+%   GPRmat              GPR matrix as returned by \"extractGPRS.m\"\r\n+%                       (parsedGPR)\r\n+%   GPRrxns             reaction cell as returned by \"extractGPRS.m\"\r\n+%                       (corrRxn)\r\n+%   core                cell with reactions names that are manually added to\r\n+%                       the core reaction set (i.e. {'Biomass_reaction'})\r\n+%   threshold_high                  reactions with expression higher than this threshold will be in \r\n+%                       the core reaction set (expression threshold)\r\n+%   checkv              Boolean variable:\r\n+%                           0: don't use salvage pathway and functionality check\r\n+%                           1: include salvage pathway and functionality\r\n+%                           check\r\n+%   eta                 tradeoff between removing core and zero-expression\r\n+%                       reactions (1/3)\r\n+%   tol                 tolerance by which reaction fluxes are defined inactive\r\n+%                       (recommended lowest value 1e-8 since solver tolerance is 1e-9)\r\n+%\r\n+%\r\n+%OUTPUTS\r\n+%\r\n+%   tissueModel         extracted model\r\n+%\r\n+%*Wang et al. (2012). Reconstrcution of genome-scale metabolic models for\r\n+%126 human tissues using mCADRE. BMC Syst. Biol. 6, 153.\r\n+%\r\n+%This script is an adapted version of the implementation from\r\n+%https://github.com/jaeddy/mcadre. Modified by S. Opdam and A. Richelle,\r\n+%May 2017.\r\n+\r\n+%Note that \"Biomass_reaction\" reaction is hard-coded to be active\r\n+\r\n+\r\n+\r\n+% Set parameters for mcadre\r\n+    %method = 1; % fastFVA\r\n+    method = 2; % fastcc\r\n+    salvageCheck = checkv;\r\n+    metaboliteCheck = checkv;\r\n+    \r\n+    %Confidence scores formatting\r\n+    confidenceScores=zeros(length(model.rxns),1);\r\n+    for i = 1:length(model.rxns)\r\n+        if ~isempty(model.confidenceScores{i})\r\n+            confidenceScores(i) = str2num(model.confidenceScores{i});\r\n+        else\r\n+            confidenceScores(i) = NaN; %confidence scores which are not given\r\n+        end\r\n+    end\r\n+    \r\n+    %Gene expression data [0,1], scaled w.r.t. upper threshold (threshold_high)\r\n+    expression = gene_exp/threshold_high;\r\n+    expression(expression >= 1) = 1;\r\n+    \r\n+    % Run mcadre\r\n+    [PM, GM, C, NC, Z, model_C, pruneTime, cRes] = mcadre(model, gene_names, expression, confidenceScores, salvageCheck, metaboliteCheck, core, method, GPRrxns, GPRmat, eta, tol);\r\n+    tissueModel = PM;\r\n+    tissueModel = removeNonUsedGenes(tissueModel);\r\n+    \r\n+    is_active = fastcc(tissueModel, tol);\r\n+    inactiveRxns = setdiff(tissueModel.rxns, tissueModel.rxns(is_active));\r\n+    if ~isempty(inactiveRxns)\r\n+        warning('Extracted model is not consistent, this might be caused by (numerical) issues in fastcc consistency checks')\r\n+    end\r\n+end\r\n+\r\n+function [PM, GM, C, NC, Z, model_C, pruneTime, cRes] = mcadre(model, G, U, confidenceScores, salvageCheck, metaboliteCheck, core, method, GPRrxns, GPRmat, eta, tol)\r\n+%INPUTS\r\n+%\tmodel               original generic model\r\n+%\tG                   list of genes in expression data\r\n+%\tU                   ubiquity scores corresponding to genes in G\r\n+%\tconfidenceScores    literature-based evidence for generic model reactions\r\n+%\tsalvageCheck        option flag for whether to perform functional check for the\r\n+%                       nucleotide salvage pathway (1) or not (0)\r\n+%\tC_H_genes           predefined high confidence reactions (optional)\r\n+%\tmethod              1 = use fastFVA (glpk) to check consistency; \r\n+%                       2 = use fastcc & cplex\r\n+%\r\n+%OUTPUTS\r\n+%\tPM                  pruned, context-specific model\r\n+%\tGM                  generic model (after removing blocked reactions)\r\n+%\tC                   core reactions in GM\r\n+%\tNC                  non-core reactions in GM\r\n+%\tZ                   reactions with zero expression (i.e., measured zero, not just\r\n+%                       missing from expression data)\r\n+%\tmodel_C             core reactions in the original model (including blocked)\r\n+%\tpruneTime           total reaction pruning time\r\n+%\tcRes                result of model checks (consistency/function)\r\n+%                       - vs. +: reaction r removed from generic model or not\r\n+%                       1 vs. 2: reaction r had zero or non-zero expression evidence\r\n+%                       -x.y: removal of reaction r corresponded with removal of y (num.) total\r\n+%                       core reactions\r\n+%                       +x.1 vs. x.0: precursor production possible after removal of \r\n+%                       reaction r or not\r\n+%                       3: removal of reaction r by itself prevented production of required\r\n+%                       metabolites (therefore was not removed)\r\n+\r\n+\r\n+\r\n+\r\n+%         if nargin < 7\r\n+%             method = 1; % fastFVA\r\n+%         end\r\n+% \r\n+%         if nargin < 6\r\n+%             core = [];\r\n+%         end\r\n+% \r\n+%         if nargin < 5\r\n+%             salvageCheck = 1;\r\n+%         end\r\n+\r\n+        % Generate order for reaction removal\r\n+\r\n+        % Gene ubiquity scores are converted to reaction expression evidence to\r\n+        % define the core (C) and non-core (NC) reaction sets. Inactive reactions\r\n+        % are identified and removed from the global model to produce the generic\r\n+        % model (GM) for subsequent pruning. Non-core reactions are ordered first\r\n+        % by expression and then by connectivity evidence to give the list P. Any\r\n+        % reactions with zero expression (i.e., associated, but non-expressed\r\n+        % genes) are also listed in the vector Z.\r\n+\r\n+        %display('Processing inputs and ranking reactions...')\r\n+\r\n+        [GM, C, NC, P, Z, model_C] = rank_reactions(model, G, U, confidenceScores, core, method, GPRrxns, GPRmat);\r\n+\r\n+        % Define inputs to the model pruning step\r\n+\r\n+        % Define core vs. non-core ratio threshold for removing reactions\r\n+        %eta = 1/3;\r\n+\r\n+        % Check functionality of generic model\r\n+        %changeCobraSolver('glpk');\r\n+        %load('precursorMets');\r\n+        \r\n+        %FIX: added option to skip metabolite check\r\n+        if metaboliteCheck == 1\r\n+            precursorMets = {'3pg[c]';'accoa[m]';'akg[m]';'e4p[c]';'f6p[c]';'g3p[c]';'g6p[c]';'oaa[m]';'pep[c]';'pyr[c]';'r5p[c]';'succoa[m]'};\r\n+            nonEssentialAA = {'ala-L[c]';'arg-L[c]';'asn-L[c]';'asp-L[c]';'gln-L[c]';'glu-L[c]';'gly[c]';'pro-L[c]';'ser-L[c]'};\r\n+            nucleotide = {'ctp[c]';'utp[c]'};\r\n+            lipid = {'pmtcoa[c]';'chsterol[c]';'tag_hs[c]';'dag_hs[c]';'mag_hs[c]';'crm_hs[c]';'pa_hs[c]';'pe_hs[c]';'ps_hs[c]'};\r\n+            precursorMets=[precursorMets;nonEssentialAA;nucleotide;lipid];\r\n+        else\r\n+            precursorMets={};\r\n+        end\r\n+\r\n+        genericStatus = check_model_function(GM, 'requiredMets', precursorMets);\r\n+\r\n+        if genericStatus\r\n+            %display('Generic model passed precursor metabolites test');\r\n+            if check_salvage_path(GM)\r\n+                %display('Generic model passed salvage path test');\r\n+            else\r\n+                %warning('Generic model passed precursor metabolites test');\r\n+            end\r\n+        \r\n+        % If generic functionality test is passed, prune reactions\r\n+            %display('Pruning reactions...')\r\n+            t0 = clock;\r\n+\r\n+            [PM, cRes] = prune_model(GM, P, C, Z, eta, precursorMets, salvageCheck, method, tol);\r\n+\r\n+            pruneTime = etime(clock,t0);\r\n+        else\r\n+            error('Generic model failed precursor metabolites test')\r\n+        end\r\n+end\r\n+\r\n+function [GM, C, NC, P, Z, model_C] = rank_reactions(model, G, U, confidenceScores, core, method, GPRrxns, GPRmat)\r\n+%INPUTS\r\n+%\tmodel\r\n+%\tgene IDs from expression data\r\n+%\tgene ubiquity scores (i.e., from mas5callToExpression)\r\n+%\tC_H_genes\thigh confidence genes (optional)\r\n+%\r\n+%OUTPUTS\r\n+%\tGM              generic model with inactive reactions removed\r\n+%\tC               core reactions\r\n+%\tNC              non-core reactions\r\n+%\tP               removal order of non-core reactions\r\n+\r\n+    if nargin < 6\r\n+        method = 1; % fastFVA\r\n+    end\r\n+\r\n+    % Parse GPRs\r\n+    if nargin < 7\r\n+        %disp('No GPRs as input, calculate GPRs')\r\n+        [GPRrxns, GPRmat] = parse_gprs(model);\r\n+    end\r\n+\r\n+    % Map high confidence genes to reactions\r\n+    % FIX: Modified to work with core reactions instead of core genes\r\n+    if nargin > 4\r\n+        is_C_H = false(size(model.rxns));\r\n+        for i = 1:length(core)\r\n+            ind = find(ismember(model.rxns,core{i}));\r\n+            is_C_H(ind) = true;\r\n+            %disp(['Reaction: ',model.rxns{ind},' was added to core'])\r\n+        end\r\n+    else is_C_H = false(size(model.rxns));\r\n+    end\r\n+\r\n+\r\n+    % Map gene ubiqiuty scores to reactions\r\n+    U_GPR = map_gene_scores_to_rxns(model, G, U, GPRmat);\r\n+\r\n+\r\n+    % Determine confidence level-based evidence\r\n+    E_L = confidenceScores;\r\n+    % Reactions with no confidence information should not be ranked higher than\r\n+    % those with non-zero confidence\r\n+    E_L(isnan(E_L)) = 0;\r\n+\r\n+\r\n+    % Calculate expression-based evidence\r\n+    E_X = calc_expr_evidence(model, GPRrxns, U_GPR, is_C_H);\r\n+\r\n+    % FIX: In preprocessing it was decided which reactions go into core,\r\n+    % therefore core is only expression evidence of 1. (core = expression > threshold_high)\r\n+    C = model.rxns(E_X >= 1);\r\n+    model_C = C;\r\n+\r\n+\r\n+    % Initialize the consistent generic model & update evidence vectors\r\n+    % I'm not 100% convinced that we should do this before calculating the\r\n+    % connectivity-based evidence, but I'll look into this more later.\r\n+\r\n+    % FIX: This step is skipped, since the model input was already\r\n+    % consistent\r\n+    %[GM, C, E_X, E_L] = initialize_generic_model(model, C, ...\r\n+    %    E_X, confidenceScores, method);\r\n+    GM = model;\r\n+\r\n+    R_G = GM.rxns; \r\n+    [NC, NC_idx] = setdiff(R_G, C);\r\n+\r\n+\r\n+    % Calculate connectivity-based evidence\r\n+    E_C = calc_conn_evidence(GM, E_X);\r\n+\r\n+\r\n+    % Rank non-core reactions\r\n+    E_X_NC = E_X(NC_idx); % expression-based evidence for non-core reactions\r\n+    E_C_NC = E_C(NC_idx); % connectivity-based evidence for non-core reactions\r\n+    E_L_NC = E_L(NC_idx); % literature-based evidence for non-core reactions\r\n+    [E_NC, NC_order] = sortrows([E_X_NC, E_C_NC, E_L_NC], [1, 2, 3]);\r\n+    P = NC(NC_order); % ordered (ranked) non-core reactions\r\n+\r\n+\r\n+    % Identify zero-expression reactions\r\n+    Z = P(E_NC(:, 1) == -1e-6);\r\n+end\r\n+\r\n+function U_GPR = map_gene_scores_to_rxns(model, G, U, GPRmat)\r\n+    if ~iscellstr(model.genes)\r\n+        genes = strtrim(cellstr(num2str(model.genes)));\r\n+    else genes = model.genes;\r\n+    end\r\n+    \r\n+    % FIX: gene id's and model gene id's already match\r\n+    %genes = regexprep(genes, '\\.[0-9]', '');\r\n+    U_GPR = nan(size(GPRmat));\r\n+    [geneInt, G_idx] = intersect(G, genes);\r\n+    for i = 1:numel(geneInt)\r\n+        gene_GPR = strcmp(GPRmat, geneInt{i});\r\n+        U_GPR(gene_GPR) = U(G_idx(i));\r\n+    end\r\n+\r\n+    % Penalize genes with zero expression, such that corresponding reactions\r\n+    % will be ranked lower than non-gene associated reactions.\r\n+    U_GPR(U_GPR == 0) = -1e-6;\r\n+end\r\n+\r\n+function [GPRrxns, GPRmat] = parse_gprs(model)\r\n+    warning('parse_gprs function was not validated!')\r\n+    numGPRs = cellfun('length', regexp(model.grRules, 'or'));\r\n+\r\n+    noRules = cellfun('isempty', model.grRules);\r\n+    numGPRs(~noRules) = numGPRs(~noRules) + 1;\r\n+\r\n+    numRows = sum(numGPRs); numCols = max(numGPRs);\r\n+\r\n+    GPRmat = repmat({''}, numRows, numCols);\r\n+    GPRrxns = repmat({''}, numRows, 1);\r\n+\r\n+    count = 1;\r\n+    for i = 1:numel(model.grRules)\r\n+        if numel(model.grRules{i})\r\n+            ruleGPRs = regexp(model.grRules{i}, 'or', 'split');\r\n+            ruleGPRs = regexprep(ruleGPRs, '[\\s\\(\\)]', '');\r\n+            for j = 1:numel(ruleGPRs)\r\n+                GPR = regexp(ruleGPRs{j}, 'and', 'split');\r\n+                GPRmat(count,1:numel(GPR)) = GPR;\r\n+                GPRrxns(count) = model.rxns(i);\r\n+                count = count + 1;\r\n+            end\r\n+        end\r\n+    end\r\n+\r\n+    GPRmat(:,sum(~cellfun('isempty', GPRmat), 1) == 0) = [];\r\n+    GPRmat = regexprep(GPRmat, '\\.[0-9]', '');\r\n+end\r\n+\r\n+function E_X = calc_expr_evidence(model, GPRrxns, U_GPR, is_C_H)\r\n+    E_X = zeros(size(model.rxns));\r\n+    U_GPR_min = min(U_GPR, [], 2);\r\n+    for i = 1:numel(model.rxns)\r\n+        rxn_GPRs = strmatch(model.rxns{i}, GPRrxns, 'exact');\r\n+        if numel(rxn_GPRs)\r\n+            E_X(i) = max(U_GPR_min(rxn_GPRs));\r\n+        end\r\n+    end\r\n+    % For reactions with no corresponding probe in expression data\r\n+    E_X(isnan(E_X)) = 0;\r\n+    E_X(is_C_H) = 1;\r\n+end\r\n+\r\n+function E_C = calc_conn_evidence(model, E_X)\r\n+    % S matrix is binarized to indicate metabolite participation in each reaction\r\n+    Sbin = double(model.S ~= 0);\r\n+\r\n+    % Adjacency matrix (i.e., binary reaction connectivity); the connection between\r\n+    % a reaction and itself is ignored by subtracting the identity matrix\r\n+    A = full(double(Sbin' * Sbin ~= 0));\r\n+    A = A - eye(size(A));\r\n+\r\n+    % Influence matrix; describes the divided connectivity of reactions --\r\n+    % e.g., if R1 is connected to 4 reactions, its influence on each of those\r\n+    % reactions would be 0.25\r\n+    I = A ./ repmat(sum(A, 2), 1, size(A, 2));\r\n+\r\n+    % Weighted influence matrix; each reaction's influence on others is\r\n+    % weighted by its expression score\r\n+    WI = repmat(E_X, 1, size(A, 2)) .* I;\r\n+\r\n+    % Connectivity score; sum the influence of all connected reactions\r\n+    E_C = sum(WI)';\r\n+end\r\n+\r\n+function [requiredMetsStatus, time] = check_model_function(model, varargin)\r\n+%INPUTS\r\n+%   model\r\n+% - optional inputs:\r\n+%       'requiredMets', metList\r\n+%       'biomass', biomassRxn\r\n+%       'media', mediaDef\r\n+\r\n+    % FIX: for functionality checks do not constrain biomass\r\n+    model = changeRxnBounds(model,'Biomass_reaction',0,'l');\r\n+    \r\n+    % Parse input parameters\r\n+    if numel(varargin)\r\n+        if rem(numel(varargin), 2) == 0\r\n+            options = {'requiredMets', 'biomass', 'media'};\r\n+            for i = 1:2:numel(varargin)\r\n+                argname = varargin{i}; argval = varargin{i + 1};\r\n+                option = find(strncmpi(argname, options, numel(argname)));\r\n+                if ~isempty(option)\r\n+                    switch option\r\n+                        case 1\r\n+                            metList = argval;\r\n+                        case 2\r\n+                            error('%s option not yet implemented.', argname);\r\n+                            % biomassRxn = argval;\r\n+                        case 3\r\n+                            error('%s option not yet implemented.', argname);\r\n+                            % mediaDef = argval;\r\n+                    end\r\n+                else error('Unknown option %s.', argname)\r\n+                end\r\n+            end\r\n+        else error('Incorrect number of input arguments to function %s.', ...\r\n+                mfilename);\r\n+        end\r\n+    end\r\n+\r\n+    %\r\n+    t0 = clock;\r\n+    \r\n+    %FIX: if metlist is empty, skip the step and always say the test is passed\r\n+    if isempty(metList)\r\n+        requiredMetsStatus = true;\r\n+        time = etime(clock, t0);\r\n+    else\r\n+        % Identify exchange reactions in the model\r\n+        exRxns = find_ex_rxns(model);\r\n+\r\n+        % Turn off uptake of organic metabolites\r\n+        if exist('mediaDef', 'var')\r\n+            model = set_media_ex_bounds(model); % not implemented in this version\r\n+        else\r\n+            model = set_organic_met_bounds(model, exRxns);\r\n+        end\r\n+\r\n+        % Allow uptake of glucose and CO2\r\n+        warning off all\r\n+        model = changeRxnBounds(model, 'EX_glc(e)', -5, 'l');\r\n+        model = changeRxnBounds(model, 'EX_co2(e)', -1000, 'l');\r\n+        warning on all\r\n+\r\n+        % Add demand reactions for required metabolites\r\n+        if exist('metList', 'var')\r\n+            [model, requiredRxns] = specify_required_rxns(model, metList);\r\n+        else requiredRxns = {};\r\n+        end\r\n+\r\n+        if exist('biomassRxn', 'var')\r\n+            requiredRxns = [requiredRxns, biomassRxn]; % not implemented in this version\r\n+        end\r\n+\r\n+        inactiveRequired = check_rxn_flux(model, requiredRxns);\r\n+\r\n+        requiredMetsStatus = ~numel(inactiveRequired);\r\n+        time = etime(clock, t0);\r\n+    end\r\n+end\r\n+\r\n+function exRxns = find_ex_rxns(model)\r\n+    % Note: this function identifies all source or sink reactions, not just those\r\n+    % exchanging metabolites into and out of the extracellular space\r\n+\r\n+    % Find indices of out-only reactions\r\n+    indOutRxns = sum(model.S > 0) > 0 & sum(model.S < 0) == 0;\r\n+\r\n+    % Find indices of in-only reactions\r\n+    indInRxns = sum(model.S < 0) > 0 & sum(model.S > 0) == 0;\r\n+\r\n+    % Define exchange reactions as the union of out- and in-only\r\n+    indExRxns = indOutRxns | indInRxns;\r\n+\r\n+    exRxns = model.rxns(indExRxns);\r\n+end\r\n+\r\n+function model = set_organic_met_bounds(model, exRxns)\r\n+    % Identify all exchange reactions that include organic metabolites\r\n+    organicExRxns = find_organic_ex_rxns(model, exRxns);\r\n+\r\n+    % Reset all lower bounds for organic reactions to 0 to turn off uptake\r\n+    warning off all\r\n+    model = changeRxnBounds(model, organicExRxns, 0, 'l');\r\n+    warning on all\r\n+end\r\n+\r\n+function organicExRxns = find_organic_ex_rxns(model, exRxns)\r\n+    % Note: should add a warning if the metFormulas field is empty\r\n+    % Organic metabolites are defined as those containing carbon (C) and hydrogen\r\n+    % (H); these are identified by checking molecular formulas\r\n+    if isempty(model.metFormulas); warning('metFormulas field is empty'); end\r\n+    carbonMets = ~cellfun('isempty', regexp(model.metFormulas, 'C'));\r\n+    hydrogenMets = ~cellfun('isempty', regexp(model.metFormulas, 'H'));\r\n+    is_organic = carbonMets & hydrogenMets;\r\n+    organicMets = model.mets(is_organic);\r\n+\r\n+    organicRxns = findRxnsFromMets(model, organicMets);\r\n+    organicExRxns = intersect(organicRxns, exRxns);\r\n+\r\n+    % The following reactions exchange organic metabolites (e.g., R-groups that\r\n+    % comprise lipid tails), but don't contain H in their specified formulas; OR,\r\n+    % as in the case of Tyr-ggn, include protein compounds\r\n+    organicExRxns = [organicExRxns; ...\r\n+        'EX_Rtotal(e)'; 'EX_Rtotal2(e)'; 'EX_Rtotal3(e)'; 'EX_Tyr_ggn(e)';'EX_peplys(e)']; % ; ...\r\n+        % 'UP_Tyr_ggn[c]']; % This rxn is not in Recon 1 - may be something specific\r\n+        % to Recon 2...\r\n+        % FIX: added PEPLYS\r\n+end\r\n+\r\n+function [model, requiredRxns] = specify_required_rxns(model, metList)\r\n+    % note: the evalc() function is used to suppress printed outputs from Cobra\r\n+    % Toolbox functions addDemandReaction() and addReaction()\r","path":"src/dataIntegration/transcriptomics/call_mCADRE.m","position":485,"original_position":485,"commit_id":"b5caa2c87f21055a9d9b98ac9f90f4901d840b04","original_commit_id":"251b8349d996f956db17196e38700087b8391839","user":{"login":"arichelle","id":14930292,"avatar_url":"https://avatars0.githubusercontent.com/u/14930292?v=3","gravatar_id":"","url":"https://api.github.com/users/arichelle","html_url":"https://github.com/arichelle","followers_url":"https://api.github.com/users/arichelle/followers","following_url":"https://api.github.com/users/arichelle/following{/other_user}","gists_url":"https://api.github.com/users/arichelle/gists{/gist_id}","starred_url":"https://api.github.com/users/arichelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arichelle/subscriptions","organizations_url":"https://api.github.com/users/arichelle/orgs","repos_url":"https://api.github.com/users/arichelle/repos","events_url":"https://api.github.com/users/arichelle/events{/privacy}","received_events_url":"https://api.github.com/users/arichelle/received_events","type":"User","site_admin":false},"body":"this function has been removed in the new scripts","created_at":"2017-05-17T15:55:56Z","updated_at":"2017-05-17T15:55:57Z","html_url":"https://github.com/opencobra/cobratoolbox/pull/426#discussion_r117042199","pull_request_url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426","_links":{"self":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/comments/117042199"},"html":{"href":"https://github.com/opencobra/cobratoolbox/pull/426#discussion_r117042199"},"pull_request":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426"}}},"pull_request":{"url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426","id":120218812,"html_url":"https://github.com/opencobra/cobratoolbox/pull/426","diff_url":"https://github.com/opencobra/cobratoolbox/pull/426.diff","patch_url":"https://github.com/opencobra/cobratoolbox/pull/426.patch","issue_url":"https://api.github.com/repos/opencobra/cobratoolbox/issues/426","number":426,"state":"open","locked":false,"title":"Scripts and data related to Extraction Methods","user":{"login":"arichelle","id":14930292,"avatar_url":"https://avatars0.githubusercontent.com/u/14930292?v=3","gravatar_id":"","url":"https://api.github.com/users/arichelle","html_url":"https://github.com/arichelle","followers_url":"https://api.github.com/users/arichelle/followers","following_url":"https://api.github.com/users/arichelle/following{/other_user}","gists_url":"https://api.github.com/users/arichelle/gists{/gist_id}","starred_url":"https://api.github.com/users/arichelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arichelle/subscriptions","organizations_url":"https://api.github.com/users/arichelle/orgs","repos_url":"https://api.github.com/users/arichelle/repos","events_url":"https://api.github.com/users/arichelle/events{/privacy}","received_events_url":"https://api.github.com/users/arichelle/received_events","type":"User","site_admin":false},"body":"\r\n","created_at":"2017-05-11T22:58:28Z","updated_at":"2017-05-17T15:55:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"20f2c91669877fd2f846ba3c2f2d044421303f3d","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426/commits","review_comments_url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426/comments","review_comment_url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opencobra/cobratoolbox/issues/426/comments","statuses_url":"https://api.github.com/repos/opencobra/cobratoolbox/statuses/b5caa2c87f21055a9d9b98ac9f90f4901d840b04","head":{"label":"arichelle:add-extraction-methods","ref":"add-extraction-methods","sha":"b5caa2c87f21055a9d9b98ac9f90f4901d840b04","user":{"login":"arichelle","id":14930292,"avatar_url":"https://avatars0.githubusercontent.com/u/14930292?v=3","gravatar_id":"","url":"https://api.github.com/users/arichelle","html_url":"https://github.com/arichelle","followers_url":"https://api.github.com/users/arichelle/followers","following_url":"https://api.github.com/users/arichelle/following{/other_user}","gists_url":"https://api.github.com/users/arichelle/gists{/gist_id}","starred_url":"https://api.github.com/users/arichelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arichelle/subscriptions","organizations_url":"https://api.github.com/users/arichelle/orgs","repos_url":"https://api.github.com/users/arichelle/repos","events_url":"https://api.github.com/users/arichelle/events{/privacy}","received_events_url":"https://api.github.com/users/arichelle/received_events","type":"User","site_admin":false},"repo":{"id":90882885,"name":"cobratoolbox","full_name":"arichelle/cobratoolbox","owner":{"login":"arichelle","id":14930292,"avatar_url":"https://avatars0.githubusercontent.com/u/14930292?v=3","gravatar_id":"","url":"https://api.github.com/users/arichelle","html_url":"https://github.com/arichelle","followers_url":"https://api.github.com/users/arichelle/followers","following_url":"https://api.github.com/users/arichelle/following{/other_user}","gists_url":"https://api.github.com/users/arichelle/gists{/gist_id}","starred_url":"https://api.github.com/users/arichelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arichelle/subscriptions","organizations_url":"https://api.github.com/users/arichelle/orgs","repos_url":"https://api.github.com/users/arichelle/repos","events_url":"https://api.github.com/users/arichelle/events{/privacy}","received_events_url":"https://api.github.com/users/arichelle/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/arichelle/cobratoolbox","description":"The COnstraint-Based Reconstruction and Analysis Toolbox","fork":true,"url":"https://api.github.com/repos/arichelle/cobratoolbox","forks_url":"https://api.github.com/repos/arichelle/cobratoolbox/forks","keys_url":"https://api.github.com/repos/arichelle/cobratoolbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/arichelle/cobratoolbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/arichelle/cobratoolbox/teams","hooks_url":"https://api.github.com/repos/arichelle/cobratoolbox/hooks","issue_events_url":"https://api.github.com/repos/arichelle/cobratoolbox/issues/events{/number}","events_url":"https://api.github.com/repos/arichelle/cobratoolbox/events","assignees_url":"https://api.github.com/repos/arichelle/cobratoolbox/assignees{/user}","branches_url":"https://api.github.com/repos/arichelle/cobratoolbox/branches{/branch}","tags_url":"https://api.github.com/repos/arichelle/cobratoolbox/tags","blobs_url":"https://api.github.com/repos/arichelle/cobratoolbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/arichelle/cobratoolbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/arichelle/cobratoolbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/arichelle/cobratoolbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/arichelle/cobratoolbox/statuses/{sha}","languages_url":"https://api.github.com/repos/arichelle/cobratoolbox/languages","stargazers_url":"https://api.github.com/repos/arichelle/cobratoolbox/stargazers","contributors_url":"https://api.github.com/repos/arichelle/cobratoolbox/contributors","subscribers_url":"https://api.github.com/repos/arichelle/cobratoolbox/subscribers","subscription_url":"https://api.github.com/repos/arichelle/cobratoolbox/subscription","commits_url":"https://api.github.com/repos/arichelle/cobratoolbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/arichelle/cobratoolbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/arichelle/cobratoolbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/arichelle/cobratoolbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/arichelle/cobratoolbox/contents/{+path}","compare_url":"https://api.github.com/repos/arichelle/cobratoolbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/arichelle/cobratoolbox/merges","archive_url":"https://api.github.com/repos/arichelle/cobratoolbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/arichelle/cobratoolbox/downloads","issues_url":"https://api.github.com/repos/arichelle/cobratoolbox/issues{/number}","pulls_url":"https://api.github.com/repos/arichelle/cobratoolbox/pulls{/number}","milestones_url":"https://api.github.com/repos/arichelle/cobratoolbox/milestones{/number}","notifications_url":"https://api.github.com/repos/arichelle/cobratoolbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/arichelle/cobratoolbox/labels{/name}","releases_url":"https://api.github.com/repos/arichelle/cobratoolbox/releases{/id}","deployments_url":"https://api.github.com/repos/arichelle/cobratoolbox/deployments","created_at":"2017-05-10T15:59:12Z","updated_at":"2017-05-10T15:59:18Z","pushed_at":"2017-05-17T15:45:49Z","git_url":"git://github.com/arichelle/cobratoolbox.git","ssh_url":"git@github.com:arichelle/cobratoolbox.git","clone_url":"https://github.com/arichelle/cobratoolbox.git","svn_url":"https://github.com/arichelle/cobratoolbox","homepage":"http://opencobra.github.io/cobratoolbox/","size":446754,"stargazers_count":0,"watchers_count":0,"language":"Matlab","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"opencobra:develop","ref":"develop","sha":"689c239a932685d5ea69a048fd481fea7614762e","user":{"login":"opencobra","id":2708410,"avatar_url":"https://avatars3.githubusercontent.com/u/2708410?v=3","gravatar_id":"","url":"https://api.github.com/users/opencobra","html_url":"https://github.com/opencobra","followers_url":"https://api.github.com/users/opencobra/followers","following_url":"https://api.github.com/users/opencobra/following{/other_user}","gists_url":"https://api.github.com/users/opencobra/gists{/gist_id}","starred_url":"https://api.github.com/users/opencobra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opencobra/subscriptions","organizations_url":"https://api.github.com/users/opencobra/orgs","repos_url":"https://api.github.com/users/opencobra/repos","events_url":"https://api.github.com/users/opencobra/events{/privacy}","received_events_url":"https://api.github.com/users/opencobra/received_events","type":"Organization","site_admin":false},"repo":{"id":6512296,"name":"cobratoolbox","full_name":"opencobra/cobratoolbox","owner":{"login":"opencobra","id":2708410,"avatar_url":"https://avatars3.githubusercontent.com/u/2708410?v=3","gravatar_id":"","url":"https://api.github.com/users/opencobra","html_url":"https://github.com/opencobra","followers_url":"https://api.github.com/users/opencobra/followers","following_url":"https://api.github.com/users/opencobra/following{/other_user}","gists_url":"https://api.github.com/users/opencobra/gists{/gist_id}","starred_url":"https://api.github.com/users/opencobra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opencobra/subscriptions","organizations_url":"https://api.github.com/users/opencobra/orgs","repos_url":"https://api.github.com/users/opencobra/repos","events_url":"https://api.github.com/users/opencobra/events{/privacy}","received_events_url":"https://api.github.com/users/opencobra/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opencobra/cobratoolbox","description":"The COnstraint-Based Reconstruction and Analysis Toolbox","fork":false,"url":"https://api.github.com/repos/opencobra/cobratoolbox","forks_url":"https://api.github.com/repos/opencobra/cobratoolbox/forks","keys_url":"https://api.github.com/repos/opencobra/cobratoolbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opencobra/cobratoolbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opencobra/cobratoolbox/teams","hooks_url":"https://api.github.com/repos/opencobra/cobratoolbox/hooks","issue_events_url":"https://api.github.com/repos/opencobra/cobratoolbox/issues/events{/number}","events_url":"https://api.github.com/repos/opencobra/cobratoolbox/events","assignees_url":"https://api.github.com/repos/opencobra/cobratoolbox/assignees{/user}","branches_url":"https://api.github.com/repos/opencobra/cobratoolbox/branches{/branch}","tags_url":"https://api.github.com/repos/opencobra/cobratoolbox/tags","blobs_url":"https://api.github.com/repos/opencobra/cobratoolbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opencobra/cobratoolbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opencobra/cobratoolbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/opencobra/cobratoolbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opencobra/cobratoolbox/statuses/{sha}","languages_url":"https://api.github.com/repos/opencobra/cobratoolbox/languages","stargazers_url":"https://api.github.com/repos/opencobra/cobratoolbox/stargazers","contributors_url":"https://api.github.com/repos/opencobra/cobratoolbox/contributors","subscribers_url":"https://api.github.com/repos/opencobra/cobratoolbox/subscribers","subscription_url":"https://api.github.com/repos/opencobra/cobratoolbox/subscription","commits_url":"https://api.github.com/repos/opencobra/cobratoolbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/opencobra/cobratoolbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/opencobra/cobratoolbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/opencobra/cobratoolbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/opencobra/cobratoolbox/contents/{+path}","compare_url":"https://api.github.com/repos/opencobra/cobratoolbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opencobra/cobratoolbox/merges","archive_url":"https://api.github.com/repos/opencobra/cobratoolbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opencobra/cobratoolbox/downloads","issues_url":"https://api.github.com/repos/opencobra/cobratoolbox/issues{/number}","pulls_url":"https://api.github.com/repos/opencobra/cobratoolbox/pulls{/number}","milestones_url":"https://api.github.com/repos/opencobra/cobratoolbox/milestones{/number}","notifications_url":"https://api.github.com/repos/opencobra/cobratoolbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opencobra/cobratoolbox/labels{/name}","releases_url":"https://api.github.com/repos/opencobra/cobratoolbox/releases{/id}","deployments_url":"https://api.github.com/repos/opencobra/cobratoolbox/deployments","created_at":"2012-11-02T20:38:05Z","updated_at":"2017-05-16T20:05:08Z","pushed_at":"2017-05-17T15:45:50Z","git_url":"git://github.com/opencobra/cobratoolbox.git","ssh_url":"git@github.com:opencobra/cobratoolbox.git","clone_url":"https://github.com/opencobra/cobratoolbox.git","svn_url":"https://github.com/opencobra/cobratoolbox","homepage":"https://opencobra.github.io/cobratoolbox/","size":446023,"stargazers_count":44,"watchers_count":44,"language":"Matlab","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":99,"mirror_url":null,"open_issues_count":16,"forks":99,"open_issues":16,"watchers":44,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426"},"html":{"href":"https://github.com/opencobra/cobratoolbox/pull/426"},"issue":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/issues/426"},"comments":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/issues/426/comments"},"review_comments":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426/comments"},"review_comment":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/pulls/426/commits"},"statuses":{"href":"https://api.github.com/repos/opencobra/cobratoolbox/statuses/b5caa2c87f21055a9d9b98ac9f90f4901d840b04"}}}}
{"actor":{"display_login":"arichelle"}}