From c83d1c56b1131bb0ef91c44e458391aa12fe544a Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Tue, 6 Oct 2026 17:19:18 +0200 Subject: [PATCH 1/2] fix: prefix whole gene ids in grRules in addIdentifierPrefix Gene ids with a dash, dot or colon (5-HT1A) got a prefix at every word start in grRules but one prefix in model.genes, so exportModel failed on models with such genes. --- conversion/addIdentifierPrefix.m | 22 ++++++++++++++++++---- testing/function_tests/tConversion.m | 11 +++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/conversion/addIdentifierPrefix.m b/conversion/addIdentifierPrefix.m index 3f0629da5..cf6b205f9 100644 --- a/conversion/addIdentifierPrefix.m +++ b/conversion/addIdentifierPrefix.m @@ -60,10 +60,8 @@ currField = strcat(currPrefix, currField); hasChanged(toChangeIdx(i)) = true; - if strcmp(currName,'genes') - model.grRules = regexprep(model.grRules, '(\<[0-9_a-zA-Z])', 'G_$1'); - model.grRules = regexprep(model.grRules, ' G_or ', ' or '); - model.grRules = regexprep(model.grRules, ' G_and ', ' and '); + if strcmp(currName,'genes') && isfield(model,'grRules') + model.grRules = cellfun(@(r) prefixGenes(r,currPrefix), model.grRules, 'UniformOutput', false); end model.(currName) = currField; end @@ -72,3 +70,19 @@ hasChanged = modelFields(hasChanged,:); hasChanged = append('model.', hasChanged(:,1), ' (', hasChanged(:,2), ' prefix)'); end + + +function rule = prefixGenes(rule, prefix) +% Prefix every gene in a grRule, leaving "and", "or" and brackets alone. A +% gene is everything between spaces and brackets, so ids that contain +% "-", "." or ":" get one prefix, not one per word. +[tokens, separators] = regexp(rule, '[^\s()]+', 'match', 'split'); +out = separators{1}; +for i = 1:numel(tokens) + if ~any(strcmpi(tokens{i}, {'and','or'})) + tokens{i} = [prefix tokens{i}]; + end + out = [out tokens{i} separators{i+1}]; %#ok +end +rule = out; +end diff --git a/testing/function_tests/tConversion.m b/testing/function_tests/tConversion.m index 53ed7d5a4..1c2d41954 100644 --- a/testing/function_tests/tConversion.m +++ b/testing/function_tests/tConversion.m @@ -12,6 +12,17 @@ function identifierPrefixRoundTrip(testCase) testCase.verifyEqual(mr.genes, testCase.model.genes); end + function identifierPrefixKeepsGenesWithPunctuationWhole(testCase) + % A gene id with "-", "." or ":" gets one prefix in grRules, the + % same one it gets in model.genes, so the two still match. + m = testCase.model; + m.genes = [m.genes; {'5-HT1A'; 'b2:1'}]; + m.grRules{1} = '5-HT1A and (b2:1 or 5-HT1A)'; + [mp, ~] = addIdentifierPrefix(m, 'fields', {'genes'}); + testCase.verifyEqual(mp.grRules{1}, 'G_5-HT1A and (G_b2:1 or G_5-HT1A)'); + testCase.verifyTrue(all(ismember(getGenesFromGrRules(mp.grRules(1)), mp.genes))); + end + function removeIdentifierPrefixSkipsMissingFields(testCase) % A model missing an optional field (genes, metNames, rxnNames, % id) must not make the default field list throw; it should From 3477970fe0734f0cb96b8af24cc194835b4a2ab9 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Wed, 7 Oct 2026 15:24:31 +0200 Subject: [PATCH 2/2] Update documentation --- doc/conversion/addIdentifierPrefix.html | 42 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/doc/conversion/addIdentifierPrefix.html b/doc/conversion/addIdentifierPrefix.html index 242667791..4c7b682d5 100644 --- a/doc/conversion/addIdentifierPrefix.html +++ b/doc/conversion/addIdentifierPrefix.html @@ -72,7 +72,9 @@

CROSS-REFERENCE INFORMATION ^
 </ul>
 <!-- crossreference -->
 
-
+<h2><a name=SUBFUNCTIONS ^

+

SOURCE CODE ^

+0063 if strcmp(currName,'genes') && isfield(model,'grRules') +0064 model.grRules = cellfun(@(r) prefixGenes(r,currPrefix), model.grRules, 'UniformOutput', false); +0065 end +0066 model.(currName) = currField; +0067 end +0068 end +0069 +0070 hasChanged = modelFields(hasChanged,:); +0071 hasChanged = append('model.', hasChanged(:,1), ' (', hasChanged(:,2), ' prefix)'); +0072 end +0073 +0074 +0075 function rule = prefixGenes(rule, prefix) +0076 % Prefix every gene in a grRule, leaving "and", "or" and brackets alone. A +0077 % gene is everything between spaces and brackets, so ids that contain +0078 % "-", "." or ":" get one prefix, not one per word. +0079 [tokens, separators] = regexp(rule, '[^\s()]+', 'match', 'split'); +0080 out = separators{1}; +0081 for i = 1:numel(tokens) +0082 if ~any(strcmpi(tokens{i}, {'and','or'})) +0083 tokens{i} = [prefix tokens{i}]; +0084 end +0085 out = [out tokens{i} separators{i+1}]; %#ok<AGROW> +0086 end +0087 rule = out; +0088 end
Generated by m2html © 2005
\ No newline at end of file