Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/gather_kcats/readOpenKineticsPredictorOutput.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
% constructs a kcatList structure, that can be used by assignKcatValues() to
% populate the ecModel with kcat values.
%
% CatRange predicts a class of kcat values, which OKP returns as its range
% (for instance '10 to 100 s^-1'). It is read as the geometric midpoint of
% the range, or half the upper bound for the class starting at 0.
%
% The per-entry `Source kcat` column (e.g. 'Prediction from CatPred',
% 'BRENDA', 'Sabio-RK', 'UniProt') is preserved in kcatList.kcatSource so
% that assignKcatValues() records the actual provenance of each value.
Expand Down Expand Up @@ -108,7 +112,7 @@
if isnumeric(v)
kcats(i) = v;
elseif ischar(v) || isstring(v)
kcats(i) = str2double(v);
kcats(i) = kcatFromText(char(v));
end
end

Expand Down Expand Up @@ -255,3 +259,25 @@
end
end
end

function kcat = kcatFromText(v)
% A number, or a CatRange class range '<low> to <high> s^-1' as its
% geometric midpoint (half the upper bound when the class starts at 0).
kcat = str2double(v);
if ~isnan(kcat)
return
end
bounds = regexp(strtrim(v), '^([0-9.eE+-]+)\s+to\s+([0-9.eE+-]+)(\s*s\^-1)?$', 'tokens', 'once');
if isempty(bounds)
return
end
low = str2double(bounds{1});
high = str2double(bounds{2});
if isnan(low) || isnan(high)
return
elseif low > 0
kcat = sqrt(low * high);
else
kcat = high / 2;
end
end
6 changes: 4 additions & 2 deletions src/gather_kcats/submitOpenKineticsPredictor.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
% job id is also stored in data/OKP_job.txt, so fetchOpenKineticsPredictor can
% pick it up later.
%
% Predictors available via OKP: CataPro, CatPred, DLKcat, EITLEM, KinForm-H,
% KinForm-L, UniKP (see GET /api/v1/methods/).
% Predictors available via OKP: CataPro, CatPred, CatRange, DLKcat, EITLEM,
% KinForm-H, KinForm-L, OmniESI, OmniESI-O2DENet, TurNuP, UniKP (see GET
% /api/v1/methods/). CatRange predicts a class of kcat values;
% readOpenKineticsPredictorOutput uses its geometric midpoint.
%
% Obtaining an API key:
% The OKP API requires a personal Bearer key (looks like 'ak_...'). Keys
Expand Down
1 change: 1 addition & 0 deletions test/VerificationMatrix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ gather_kcats/readDLKcatOutput.m tcm0001, tcm0002 - The test doesn't really check
gather_kcats/runDLKcat.m tcm0001, tcm0002 - The test doesn't really check the function, only that we get something
gather_kcats/assignKcatValues.m tc0011 - we did not test all possible parameterizations here
gather_kcats/writeDLKcatInput.m partly by tc0011
gather_kcats/readOpenKineticsPredictorOutput.m tc0030, tc0069
gather_kcats/reviewKcatAssignment.m Has only been tested by running it manually, not tested by test cases
gather_kcats/ecStatsFromBrenda.m Not verified against real BRENDA data in this environment -- see its own TODO comment
get_enzyme_data/calculateMW.m Not explicitly tested - The code has existed for a long time
Expand Down
29 changes: 29 additions & 0 deletions test/unit_tests/geckoCoreFunctionTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,35 @@ function testResolveOkpApiKeyResolutionOrder_tc0029(testCase)
end


function testReadOpenKineticsPredictorCatRange_tc0069(testCase)
% CatRange's prediction is a class range ('10 to 100 s^-1'), read as its
% geometric midpoint, or half the upper bound for the class from 0.
geckoPath = findGECKOroot;
adapter = ModelAdapterManager.getAdapter(fullfile(geckoPath,'test','unit_tests','ecTestGEM', 'TestGEMAdapter.m'));
model = getGeckoTestModel();
ecModel = makeEcModel(model, false, adapter);
ecModel = getECfromGEM(ecModel);
ecModel.metSmiles = repmat({''}, numel(ecModel.mets), 1);
ecModel.metSmiles(strcmp(ecModel.mets,'m1c')) = {'C(C1C)O'};

resultFile = [tempname '.csv'];
fid = fopen(resultFile,'w');
fprintf(fid,'Predicted kcat range: kcat (1/s),Source kcat,Extra Info kcat,Protein Sequence,Substrate\n');
fprintf(fid,'10 to 100 s^-1,Prediction from CatRange,Predicted range: 10 to 100 s^-1,MRAL,C(C1C)O\n');
fclose(fid);
cleanupFile = onCleanup(@() delete(resultFile));
kcatList = readOpenKineticsPredictorOutput(ecModel, 'outFile', resultFile, 'modelAdapter', adapter);
verifyEqual(testCase, kcatList.kcats, 10^1.5, 'RelTol', 1e-12)
verifyEqual(testCase, kcatList.kcatSource, {'OKP-CatRange'})

fid = fopen(resultFile,'w');
fprintf(fid,'Predicted kcat range: kcat (1/s),Source kcat,Extra Info kcat,Protein Sequence,Substrate\n');
fprintf(fid,'0 to 1e-08 s^-1,Prediction from CatRange,,MRAL,C(C1C)O\n');
fclose(fid);
kcatList = readOpenKineticsPredictorOutput(ecModel, 'outFile', resultFile, 'modelAdapter', adapter);
verifyEqual(testCase, kcatList.kcats, 5e-9, 'RelTol', 1e-12)
end

function testFetchOpenKineticsPredictorUseStoredMatchesReader_tc0030(testCase)
% Verifies fetchOpenKineticsPredictor's 'useStored' path (parsing an
% already-downloaded result file, the only path testable without a live
Expand Down
Loading