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:
11
README.md
11
README.md
@@ -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/).
|
||||
|
@@ -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"]}"))
|
||||
|
160
src/main/java/dev/pcvolkmer/onco/datamapper/genes/Gene.java
Normal file
160
src/main/java/dev/pcvolkmer/onco/datamapper/genes/Gene.java
Normal 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);
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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
44245
src/main/resources/genes.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user