1
0
mirror of https://github.com/pcvolkmer/mv64e-onkostar-data.git synced 2025-09-13 07:52:52 +00:00

feat: add "Stützende molekulare Alterationen"

This commit is contained in:
2025-07-05 01:22:41 +02:00
parent f58022f614
commit 7a782ffc54
11 changed files with 44717 additions and 6 deletions

View File

@@ -51,7 +51,7 @@ var jsonResult = Converter.toJsonString(
| IHC-Berichte | | |
| MSI-Befunde | | |
| NGS-Berichte | ⌛ | Aktuell in Arbeit |
| MTB-Beschlüsse | | Best effort: Stützende molekulare Alteration(en) aktuell nicht möglich (2) |
| MTB-Beschlüsse | | Stützende molekulare Alteration(en) für einfache Variante und CNV |
| Follow-Up Verlauf | | |
| Antrag Kostenübernahme | | |
| Antwort Kostenübernahme | | |
@@ -63,3 +63,12 @@ var jsonResult = Converter.toJsonString(
1. Nicht alle möglichen Ausprägungen in `OS.Molekulargenetik` vorhanden.
2. Nach Implementierung Mapping von HGNC-Symbol (Gen-Name) zu HGNC-ID ist die Angabe der optionalen stützenden
molekularen Alteration(en) möglich.
## Enthaltene Liste mit Genen
Es ist eine Liste mit über 43000 Genen
von [https://genenames.org](https://www.genenames.org/cgi-bin/download/custom?col=gd_hgnc_id&col=gd_app_sym&col=gd_app_name&col=gd_pub_chrom_map&col=md_ensembl_id&status=Approved&hgnc_dbtag=on&order_by=gd_app_sym_sort&format=text&submit=submit)
enthalten.
Diese Liste der Gene unterliegt der folgenden Lizenz und ist frei
verfügbar: [Creative Commons Public Domain (CC0) License](https://creativecommons.org/public-domain/cc0/).

View File

@@ -8,6 +8,7 @@ version = "0.1.0-SNAPSHOT"
var versions = mapOf(
"mtb-dto" to "0.1.0-SNAPSHOT",
"commons-csv" to "1.14.0",
"slf4j" to "2.0.17",
"junit" to "5.13.1",
"assertj" to "3.27.3",
@@ -48,6 +49,7 @@ dependencies {
prefer("4.3.8.RELEASE")
}
}
implementation("org.apache.commons:commons-csv:${versions["commons-csv"]}")
implementation("org.slf4j:slf4j-api:${versions["slf4j"]}")
testImplementation(platform("org.junit:junit-bom:${versions["junit"]}"))

View File

@@ -0,0 +1,160 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.genes;
import dev.pcvolkmer.mv64e.mtb.Chromosome;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Represents a gene
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
// Originally taken from https://github.com/pcvolkmer/onkostar-plugin-genes/blob/master/api/src/main/java/dev/pcvolkmer/onkostar/genes/Gene.java
public class Gene {
private final String hgncId;
private final String ensembleId;
private final String symbol;
private final String name;
private final String chromosome;
Gene(
String hgncId,
String ensembleId,
String symbol,
String name,
String chromosome
) {
this.hgncId = hgncId;
this.ensembleId = ensembleId;
this.symbol = symbol;
this.name = name;
this.chromosome = chromosome;
}
/**
* Returns the HGNC ID of this gene
*
* @return the HGNC ID
*/
public String getHgncId() {
return hgncId;
}
/**
* Returns the EnsemblID of this gene
*
* @return the EnsemblID
*/
public String getEnsemblId() {
return ensembleId;
}
/**
* Returns the Symbol of this gene
*
* @return the Symbol
*/
public String getSymbol() {
return symbol;
}
/**
* Returns the name of this gene
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Returns the chromosome(s) the gene is located at
*
* @return the chromosome(s)
*/
public String getChromosome() {
return chromosome;
}
/**
* Returns a list of chromosomes using form 'chr?'
*
* @return a list of chromosomes
*/
public List<Chromosome> getChromosomesInPropertyForm() {
return Arrays.stream(this.chromosome.split(" "))
.map(value -> {
try {
var pattern = Pattern.compile("^(\\d+|X|Y)");
var matcher = pattern.matcher(value);
if (matcher.find()) {
return Chromosome.forValue(String.format("chr%s", matcher.group(0)));
}
} catch (Exception e) {
// Nop
}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
* Returns a chromosome using form 'chr...?' if one (single) chromosome listed
*
* @return an <code>Optional</code> containing the chromosome
*/
public Optional<Chromosome> getSingleChromosomeInPropertyForm() {
var fixedChromosomes = this.getChromosomesInPropertyForm();
if (fixedChromosomes.size() == 1) {
return Optional.of(fixedChromosomes.get(0));
}
return Optional.empty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Gene gene = (Gene) o;
return Objects.equals(hgncId, gene.hgncId) && Objects.equals(ensembleId, gene.ensembleId) && Objects.equals(symbol, gene.symbol) && Objects.equals(name, gene.name) && Objects.equals(chromosome, gene.chromosome);
}
@Override
public int hashCode() {
return Objects.hash(hgncId, ensembleId, symbol, name, chromosome);
}
}

View File

@@ -0,0 +1,80 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.genes;
import org.apache.commons.csv.CSVFormat;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Utility class for genes
*
* @author Paul-Christian Volkmer
* @since 0.1
*/
public class GeneUtils {
private GeneUtils() {
// Empty
}
public static Optional<Gene> findByHgncId(String hgncId) {
return genes().stream().filter(gene -> gene.getHgncId().equalsIgnoreCase(hgncId)).findFirst();
}
public static Optional<Gene> findBySymbol(String symbol) {
return genes().stream().filter(gene -> gene.getSymbol().equalsIgnoreCase(symbol)).findFirst();
}
private static List<Gene> genes() {
var result = new ArrayList<Gene>();
try {
var inputStream = GeneUtils.class.getClassLoader().getResourceAsStream("genes.csv");
var parser = CSVFormat.RFC4180.builder()
.setHeader()
.setSkipHeaderRecord(true)
.setDelimiter('\t')
.get()
.parse(new InputStreamReader(inputStream));
for (var row : parser) {
result.add(
new Gene(
row.get("HGNC ID"),
row.get("Ensembl ID(supplied by Ensembl)"),
row.get("Approved symbol"),
row.get("Approved name"),
row.get("Chromosome")
)
);
}
return result;
} catch (IOException e) {
return List.of();
}
}
}

View File

@@ -72,6 +72,13 @@ public class EinzelempfehlungProzedurDataMapper extends AbstractEinzelempfehlung
);
}
// As of now: Simple variant and CSV only! - Not used but present for completeness
if (null != resultSet.getString("st_mol_alt_variante_json")) {
resultBuilder.supportingVariants(
JsonToMolAltVarianteMapper.map(resultSet.getString("st_mol_alt_variante_json"))
);
}
return resultBuilder.build();
}

View File

@@ -42,7 +42,7 @@ public class EinzelempfehlungStudieDataMapper extends AbstractEinzelempfehlungDa
@Override
protected MtbStudyEnrollmentRecommendation map(ResultSet resultSet) {
return MtbStudyEnrollmentRecommendation.builder()
var resultBuilder = MtbStudyEnrollmentRecommendation.builder()
.id(resultSet.getString("id"))
.patient(resultSet.getPatientReference())
// TODO Fix id?
@@ -56,8 +56,16 @@ public class EinzelempfehlungStudieDataMapper extends AbstractEinzelempfehlungDa
)
.medication(JsonToMedicationMapper.map(resultSet.getString("wirkstoffe_json")))
.levelOfEvidence(getLevelOfEvidence(resultSet))
.study(JsonToStudyMapper.map(resultSet.getString("studien_alle_json")))
.build();
.study(JsonToStudyMapper.map(resultSet.getString("studien_alle_json")));
// As of now: Simple variant and CSV only!
if (null != resultSet.getString("st_mol_alt_variante_json")) {
resultBuilder.supportingVariants(
JsonToMolAltVarianteMapper.map(resultSet.getString("st_mol_alt_variante_json"))
);
}
return resultBuilder.build();
}
@Override

View File

@@ -83,8 +83,11 @@ public class EinzelempfehlungWirkstoffDataMapper extends AbstractEinzelempfehlun
);
}
if (null != resultSet.getString("st_mol_alt_variante")) {
// Empty for now
// As of now: Simple variant and CSV only!
if (null != resultSet.getString("st_mol_alt_variante_json")) {
resultBuilder.supportingVariants(
JsonToMolAltVarianteMapper.map(resultSet.getString("st_mol_alt_variante_json"))
);
}
return resultBuilder.build();

View File

@@ -0,0 +1,91 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.mapper;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.pcvolkmer.mv64e.mtb.Coding;
import dev.pcvolkmer.mv64e.mtb.GeneAlterationReference;
import dev.pcvolkmer.mv64e.mtb.Reference;
import dev.pcvolkmer.onco.datamapper.exceptions.DataAccessException;
import dev.pcvolkmer.onco.datamapper.genes.GeneUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* Maps JSON strings used in Einzelempfehlung MolAltVariante
*
* @author Paul-Christian Volkmer
* @since 0.1
*/
public class JsonToMolAltVarianteMapper {
private JsonToMolAltVarianteMapper() {
// intentionally left empty
}
public static List<GeneAlterationReference> map(String studyJson) {
if (studyJson == null) {
return List.of();
}
try {
return new ObjectMapper().readValue(studyJson, new TypeReference<List<MolAltVariante>>() {
}).stream()
.map(variante -> {
var resultBuilder = GeneAlterationReference.builder();
GeneUtils.findBySymbol(variante.getGen()).ifPresent(gene -> {
resultBuilder
.gene(
Coding.builder()
.code(gene.getHgncId())
.display(gene.getSymbol())
.system("https://www.genenames.org/")
.build()
)
.variant(
Reference.builder().id(variante.id).type("Variant").build()
);
});
return resultBuilder.build();
})
.collect(Collectors.toList());
} catch (Exception e) {
throw new DataAccessException(String.format("Cannot map gene alteration for %s", studyJson));
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
private static class MolAltVariante {
private String id;
private String gen;
public String getId() {
return id;
}
public String getGen() {
return gen;
}
}
}

44245
src/main/resources/genes.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.genes;
import dev.pcvolkmer.mv64e.mtb.Chromosome;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class GeneUtilsTest {
@Test
void findByHgncId() {
var actual = GeneUtils.findByHgncId("HGNC:1097");
assertThat(actual).isPresent().hasValueSatisfying(gene -> {
assertThat(gene.getHgncId()).isEqualTo("HGNC:1097");
assertThat(gene.getEnsemblId()).isEqualTo("ENSG00000157764");
assertThat(gene.getSymbol()).isEqualTo("BRAF");
assertThat(gene.getName()).isEqualTo("B-Raf proto-oncogene, serine/threonine kinase");
assertThat(gene.getChromosome()).isEqualTo("7q34");
assertThat(gene.getSingleChromosomeInPropertyForm()).hasValue(Chromosome.CHR7);
});
}
@Test
void findByHgncSymbol() {
var actual = GeneUtils.findBySymbol("ABCD1");
assertThat(actual).isPresent().hasValueSatisfying(gene -> {
assertThat(gene.getHgncId()).isEqualTo("HGNC:61");
assertThat(gene.getEnsemblId()).isEqualTo("ENSG00000101986");
assertThat(gene.getSymbol()).isEqualTo("ABCD1");
assertThat(gene.getName()).isEqualTo("ATP binding cassette subfamily D member 1");
assertThat(gene.getChromosome()).isEqualTo("Xq28");
assertThat(gene.getSingleChromosomeInPropertyForm()).hasValue(Chromosome.CHR_X);
});
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.mapper;
import dev.pcvolkmer.mv64e.mtb.Coding;
import dev.pcvolkmer.mv64e.mtb.GeneAlterationReference;
import dev.pcvolkmer.mv64e.mtb.Reference;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class JsonToMolAltVarianteMapperTest {
@Test
void shouldMapJson() {
var json = "[{\"id\":22641112,\"ergebnis\":\"Einfache Variante (Mutation)\",\"gen\":\"BRAF\",\"exon\":\"-\",\"pathogenitaetsklasse\":\"-\"}]";
var actual = JsonToMolAltVarianteMapper.map(json);
assertThat(actual).hasSize(1);
var variant = actual.get(0);
assertThat(variant).isEqualTo(
GeneAlterationReference.builder()
.gene(Coding.builder().code("HGNC:1097").display("BRAF").system("https://www.genenames.org/").build())
.variant(Reference.builder().id("22641112").type("Variant").build())
.build()
);
}
}