Skip to content

Commit

Permalink
feat: allow lower case letters for mutations and insertions in varian…
Browse files Browse the repository at this point in the history
…t queries
  • Loading branch information
JonasKellerer authored and fengelniederhammer committed Dec 19, 2023
1 parent 7e48b26 commit fe3f8da
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ aaInsertionQuery: insertionKeyword gene ':' position ':' aaInsertionSymbol+;
aaInsertionSymbol: possiblyAmbiguousAaSymbol | '?';

nextcladePangolineageQuery: nextcladePangoLineagePrefix pangolineageQuery;
nextcladePangoLineagePrefix: 'nextcladePangoLineage:' | 'NEXTCLADEPANGOLINEAGE:';
nextcladePangoLineagePrefix: 'nextcladePangoLineage:' | 'NEXTCLADEPANGOLINEAGE:' | 'nextcladepangolineage:';

nextstrainCladeLineageQuery: nextstrainCladePrefix nextstrainCladeQuery;
nextstrainCladePrefix: 'nextstrainClade:'| 'NEXTSTRAINCLADE:';
nextstrainCladeQuery: NUMBER NUMBER nextstrainCladeCharacter | 'RECOMBINANT';
nextstrainCladePrefix: 'nextstrainClade:'| 'NEXTSTRAINCLADE:' | 'nextstrainclade:';
nextstrainCladeQuery: NUMBER NUMBER nextstrainCladeCharacter | 'RECOMBINANT' | 'recombinant';
nextstrainCladeCharacter: A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z;

gisaidCladeLineageQuery: gisaidCladePrefix gisaidCladeNomenclature;
Expand All @@ -75,37 +75,46 @@ gisaid_clade_character: A | B | C | D | E | F | G | H | I | J | K | L | M | N |

// lexer rules

A: 'A';
B: 'B';
C: 'C';
D: 'D';
E: 'E';
F: 'F';
G: 'G';
H: 'H';
I: 'I';
J: 'J';
K: 'K';
L: 'L';
M: 'M';
N: 'N';
O: 'O';
P: 'P';
Q: 'Q';
R: 'R';
S: 'S';
T: 'T';
U: 'U';
V: 'V';
W: 'W';
X: 'X';
Y: 'Y';
Z: 'Z';
A: 'A' | 'a';
B: 'B' | 'b';
C: 'C' | 'c';
D: 'D' | 'd';
E: 'E' | 'e';
F: 'F' | 'f';
G: 'G' | 'g';
H: 'H' | 'h';
I: 'I' | 'i';
J: 'J' | 'j';
K: 'K' | 'k';
L: 'L' | 'l';
M: 'M' | 'm';
N: 'N' | 'n';
O: 'O' | 'o';
P: 'P' | 'p';
Q: 'Q' | 'q';
R: 'R' | 'r';
S: 'S' | 's';
T: 'T' | 't';
U: 'U' | 'u';
V: 'V' | 'v';
W: 'W' | 'w';
X: 'X' | 'x';
Y: 'Y' | 'y';
Z: 'Z' | 'z';
MINUS: '-';
DOT: '.';
ASTERISK: '*';

NUMBER: [0-9];
WHITESPACE: [ \r\n\t] -> skip;

ORF: 'ORF1A' | 'ORF1B' | 'ORF3A' | 'ORF6' | 'ORF7A' | 'ORF7B' | 'ORF8' | 'ORF9B';
ORF1A: 'ORF1A' | 'orf1a';
ORF1B: 'ORF1B' | 'orf1b';
ORF3A: 'ORF3A' | 'orf3a';
ORF6: 'ORF6' | 'orf6';
ORF7A: 'ORF7A' | 'orf7a';
ORF7B: 'ORF7B' | 'orf7b';
ORF8: 'ORF8' | 'orf8';
ORF9B: 'ORF9B' | 'orf9b';

ORF: ORF1A | ORF1B | ORF3A | ORF6 | ORF7A | ORF7B | ORF8 | ORF9B;
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener

val expression = when (val secondSymbol = ctx.nucleotideMutationQuerySecondSymbol()) {
null -> HasNucleotideMutation(null, position)
else -> NucleotideSymbolEquals(null, position, secondSymbol.text)
else -> NucleotideSymbolEquals(null, position, secondSymbol.text.uppercase())
}

expressionStack.addLast(expression)
Expand Down Expand Up @@ -99,7 +99,7 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener
expressionStack.addLast(
NucleotideInsertionContains(
ctx.position().text.toInt(),
value,
value.uppercase(),
),
)
}
Expand All @@ -112,7 +112,7 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener

val expression = when (val aaSymbol = ctx.possiblyAmbiguousAaSymbol()) {
null -> HasAminoAcidMutation(ctx.gene().text, position)
else -> AminoAcidSymbolEquals(ctx.gene().text, position, aaSymbol.text)
else -> AminoAcidSymbolEquals(ctx.gene().text, position, aaSymbol.text.uppercase())
}

expressionStack.addLast(expression)
Expand All @@ -123,7 +123,7 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener
expressionStack.addLast(
AminoAcidInsertionContains(
ctx.position().text.toInt(),
value,
value.uppercase(),
ctx.gene().text,
),
)
Expand All @@ -136,13 +136,13 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener
override fun enterNextstrainCladeQuery(ctx: NextstrainCladeQueryContext) {
val value = when (ctx.text) {
NEXTSTRAIN_CLADE_RECOMBINANT -> ctx.text.lowercase()
else -> ctx.text
else -> ctx.text.uppercase()
}
expressionStack.addLast(StringEquals(NEXTSTRAIN_CLADE_COLUMN, value))
}

override fun enterGisaidCladeNomenclature(ctx: VariantQueryParser.GisaidCladeNomenclatureContext) {
expressionStack.addLast(StringEquals(GISAID_CLADE_COLUMN, ctx.text))
expressionStack.addLast(StringEquals(GISAID_CLADE_COLUMN, ctx.text.uppercase()))
}

private fun addPangoLineage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,15 @@ class VariantQueryFacadeTest {
assertThat(result, equalTo(NucleotideInsertionContains(1234, "GAG")))
}

@Test
fun `given a variantQuery with a 'Insertion' expression with lower case letters then returns SILO query`() {
val variantQuery = "ins_1234:gAG"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(NucleotideInsertionContains(1234, "GAG")))
}

@Test
fun `given a variantQuery with a 'Insertion' with wildcard expression then returns SILO query`() {
val variantQuery = "ins_1234:G?A?G"
Expand All @@ -287,6 +296,24 @@ class VariantQueryFacadeTest {
assertThat(result, equalTo(AminoAcidSymbolEquals("S", 501, "Y")))
}

@Test
fun `given amino acid mutation expression with lower case letters then should map to AminoAcidSymbolEquals`() {
val variantQuery = "S:n501y"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(AminoAcidSymbolEquals("S", 501, "Y")))
}

@Test
fun `given amino acid mutation expression with gene lower case letters then should map to AminoAcidSymbolEquals`() {
val variantQuery = "orf1a:N501Y"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(AminoAcidSymbolEquals("ORF1A", 501, "Y")))
}

@Test
fun `given amino acid mutation expression without first symbol then should map to AminoAcidSymbolEquals`() {
val variantQuery = "S:501Y"
Expand Down Expand Up @@ -323,6 +350,15 @@ class VariantQueryFacadeTest {
assertThat(result, equalTo(AminoAcidInsertionContains(501, "EPE", "S")))
}

@Test
fun `given a valid variantQuery with a 'AA insertion' expression with lower case then returns SILO query`() {
val variantQuery = "ins_S:501:ePe"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(AminoAcidInsertionContains(501, "EPE", "S")))
}

@Test
fun `given a valid variantQuery with a 'AA insertion' with wildcard then returns SILO query`() {
val variantQuery = "ins_S:501:E?E?"
Expand All @@ -341,6 +377,16 @@ class VariantQueryFacadeTest {
assertThat(result, equalTo(StringEquals(NEXTSTRAIN_CLADE_COLUMN, "22B")))
}

@Test
@Suppress("ktlint:standard:max-line-length")
fun `given a valid variantQuery with a 'NextstrainCladeLineage' expression in lower case then returns SILO query`() {
val variantQuery = "nextstrainClade:22b"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(StringEquals(NEXTSTRAIN_CLADE_COLUMN, "22B")))
}

@Test
fun `given a valid variantQuery with a 'NextstrainCladeLineage' recombinant expression then returns SILO query`() {
val variantQuery = "nextstrainClade:RECOMBINANT"
Expand All @@ -359,6 +405,16 @@ class VariantQueryFacadeTest {
assertThat(result, equalTo(StringEquals(GISAID_CLADE_COLUMN, "X")))
}

@Test
@Suppress("ktlint:standard:max-line-length")
fun `given a valid variantQuery with a single letter 'GisaidCladeLineage' expression with lower case then returns SILO query`() {
val variantQuery = "gisaid:x"

val result = underTest.map(variantQuery)

assertThat(result, equalTo(StringEquals(GISAID_CLADE_COLUMN, "X")))
}

@Test
fun `given a valid variantQuery with a 'GisaidCladeLineage' expression then returns SILO query`() {
val variantQuery = "gisaid:AB"
Expand Down

0 comments on commit fe3f8da

Please sign in to comment.