diff --git a/opencga-analysis/src/main/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtils.java b/opencga-analysis/src/main/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtils.java index 44e375431c1..11b828e1b3e 100644 --- a/opencga-analysis/src/main/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtils.java +++ b/opencga-analysis/src/main/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtils.java @@ -70,6 +70,7 @@ import java.util.*; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; import static org.opencb.biodata.models.clinical.ClinicalProperty.ModeOfInheritance.*; @@ -593,75 +594,10 @@ public Query parseQuery(Query query, QueryOptions queryOptions, CellBaseUtils ce individualToSample.put(entry.getKey(), samplesUidToId.get(entry.getValue())); } - String gtFilter = buildMoIGenotypeFilter(pedigree, disorder, segregationMode, individualToSample); - if (gtFilter == null) { - throw VariantQueryException.malformedParam(FAMILY_SEGREGATION, segregationMode.toString(), - "Invalid segregation mode for the family '" + family.getId() + "'"); - } - switch (segregationMode) { - case X_LINKED_DOMINANT: - case X_LINKED_RECESSIVE: - segregationChromosome = new Region("X"); - break; - case Y_LINKED: - segregationChromosome = new Region("Y"); - break; - case MITOCHONDRIAL: - segregationChromosome = new Region("MT"); - break; - default: - break; - } - if (segregationChromosome != null) { - boolean mightAddRegionFilter = true; - if (isValidParam(query, REGION.key())) { - mightAddRegionFilter = false; - List invalidRegions = new ArrayList<>(); - for (Region region : Region.parseRegions(query.getString(REGION.key()))) { - if (VariantQueryUtils.intersectRegions(segregationChromosome, region) == null) { - invalidRegions.add(region); - } - } - if (!invalidRegions.isEmpty()) { - throw VariantQueryException.unsupportedParamsCombination( - REGION, invalidRegions.toString(), - FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); - } - } - if (!xrefs.getVariants().isEmpty()) { - mightAddRegionFilter = false; - List invalidVariants = new ArrayList<>(); - for (Variant variant : xrefs.getVariants()) { - if (!variant.getChromosome().equals(segregationChromosome.getChromosome())) { - invalidVariants.add(variant); - } - } - if (!invalidVariants.isEmpty()) { - throw VariantQueryException.unsupportedParamsCombination( - ID, invalidVariants.toString(), - FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); - } - } - if (!xrefs.getGenes().isEmpty()) { - mightAddRegionFilter = false; - List invalidGenes = new ArrayList<>(); - Map geneRegionMap = cellBaseUtils.getGeneRegionMap(xrefs.getGenes(), false); - for (Map.Entry entry : geneRegionMap.entrySet()) { - if (VariantQueryUtils.intersectRegions(segregationChromosome, entry.getValue()) == null) { - invalidGenes.add(entry.getKey()); - } - } - if (!invalidGenes.isEmpty()) { - throw VariantQueryException.unsupportedParamsCombination( - GENE, invalidGenes.toString(), - FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); - } - } - if (mightAddRegionFilter) { - query.put(REGION.key(), segregationChromosome); - } - } - query.put(GENOTYPE.key(), gtFilter); + segregationChromosome = processSegregationFilter(query, cellBaseUtils, xrefs, + pedigree, segregationMode, disorder, individualToSample, + () -> VariantQueryException.malformedParam(FAMILY_SEGREGATION, segregationMode.toString(), + "Invalid segregation mode for the family '" + family.getId() + "'")); } } else { if (isValidParam(query, FAMILY_DISORDER)) { @@ -703,7 +639,7 @@ public Query parseQuery(Query query, QueryOptions queryOptions, CellBaseUtils ce } if (isValidParam(query, SAMPLE)) { - processSampleFilter(query, defaultStudyStr, token); + segregationChromosome = processSampleFilter(query, defaultStudyStr, cellBaseUtils, xrefs, token); } if (isValidParam(query, PANEL)) { @@ -1005,7 +941,9 @@ private String toIndividualId(String study, String individuaOrSample, String tok return individuaOrSample; } - private void processSampleFilter(Query query, String defaultStudyStr, String token) throws CatalogException { + private Region processSampleFilter(Query query, String defaultStudyStr, CellBaseUtils cellBaseUtils, + ParsedVariantQuery.VariantQueryXref xrefs, String token) throws CatalogException { + Region segregationChromosome = null; String sampleFilterValue = query.getString(SAMPLE.key()); if (sampleFilterValue.contains(IS)) { ClinicalProperty.ModeOfInheritance moi = null; @@ -1122,17 +1060,15 @@ private void processSampleFilter(Query query, String defaultStudyStr, String tok throw VariantQueryException.malformedParam(SAMPLE, sampleFilterValue, "Found multiple disorders for sample '" + sampleId + "'"); } - String genotypeFilter = buildMoIGenotypeFilter(pedigree, individual.getDisorders().get(0), moi); - if (genotypeFilter == null) { - throw VariantQueryException.malformedParam(SAMPLE, sampleFilterValue, - "Invalid segregation mode for the sample '" + sampleId + "'"); - } - query.put(GENOTYPE.key(), genotypeFilter); + segregationChromosome = processSegregationFilter(query, cellBaseUtils, xrefs, + pedigree, moi, individual.getDisorders().get(0), null, + () -> VariantQueryException.malformedParam(SAMPLE, sampleFilterValue, + "Invalid segregation mode for the sample '" + sampleId + "'")); query.remove(SAMPLE.key()); } } - } + return segregationChromosome; } private Set fetchIndexedSampleUIds(String token, String defaultStudyStr) throws CatalogException { @@ -1146,15 +1082,13 @@ private Set fetchIndexedSampleUIds(String token, String defaultStudyStr) t .map(Sample::getUid).collect(Collectors.toSet()); } - - private String buildMoIGenotypeFilter(Pedigree pedigree, Disorder disorder, ClinicalProperty.ModeOfInheritance moi) { - return buildMoIGenotypeFilter(pedigree, disorder, moi, null); - } - - private String buildMoIGenotypeFilter(Pedigree pedigree, Disorder disorder, ClinicalProperty.ModeOfInheritance moi, - Map pedigreeMemberToSampleId) { + private Region processSegregationFilter(Query query, CellBaseUtils cellBaseUtils, ParsedVariantQuery.VariantQueryXref xrefs, + Pedigree pedigree, + ClinicalProperty.ModeOfInheritance segregationMode, Disorder disorder, + Map pedigreeMemberToSampleId, Supplier onError) { + Region segregationChromosome = null; Map> genotypes; - switch (moi) { + switch (segregationMode) { case AUTOSOMAL_DOMINANT: genotypes = ModeOfInheritance.dominant(pedigree, disorder, ClinicalProperty.Penetrance.COMPLETE); break; @@ -1168,22 +1102,28 @@ private String buildMoIGenotypeFilter(Pedigree pedigree, Disorder disorder, Clin // genotypes = ModeOfInheritance.recessive(pedigree, disorder, ClinicalProperty.Penetrance.INCOMPLETE); // break; case X_LINKED_DOMINANT: + segregationChromosome = new Region("X"); genotypes = ModeOfInheritance.xLinked(pedigree, disorder, true, ClinicalProperty.Penetrance.COMPLETE); break; case X_LINKED_RECESSIVE: + segregationChromosome = new Region("X"); genotypes = ModeOfInheritance.xLinked(pedigree, disorder, false, ClinicalProperty.Penetrance.COMPLETE); break; case Y_LINKED: + + segregationChromosome = new Region("Y"); genotypes = ModeOfInheritance.yLinked(pedigree, disorder, ClinicalProperty.Penetrance.COMPLETE); break; case MITOCHONDRIAL: + + segregationChromosome = new Region("MT"); genotypes = ModeOfInheritance.mitochondrial(pedigree, disorder, ClinicalProperty.Penetrance.COMPLETE); break; default: - throw new IllegalArgumentException("Unexpected segregation mode " + moi); + throw new IllegalArgumentException("Unexpected segregation mode " + segregationMode); } if (ModeOfInheritance.isEmptyMapOfGenotypes(genotypes)) { - return null; + throw onError.get(); } StringBuilder sb = new StringBuilder(); @@ -1215,7 +1155,61 @@ private String buildMoIGenotypeFilter(Pedigree pedigree, Disorder disorder, Clin sb.append(gt); } } - return sb.toString(); + String gtFilter = sb.toString(); + + + if (segregationChromosome != null) { + boolean mightAddRegionFilter = true; + if (isValidParam(query, REGION.key())) { + mightAddRegionFilter = false; + List invalidRegions = new ArrayList<>(); + for (Region region : Region.parseRegions(query.getString(REGION.key()))) { + if (VariantQueryUtils.intersectRegions(segregationChromosome, region) == null) { + invalidRegions.add(region); + } + } + if (!invalidRegions.isEmpty()) { + throw VariantQueryException.unsupportedParamsCombination( + REGION, invalidRegions.toString(), + FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); + } + } + if (!xrefs.getVariants().isEmpty()) { + mightAddRegionFilter = false; + List invalidVariants = new ArrayList<>(); + for (Variant variant : xrefs.getVariants()) { + if (!variant.getChromosome().equals(segregationChromosome.getChromosome())) { + invalidVariants.add(variant); + } + } + if (!invalidVariants.isEmpty()) { + throw VariantQueryException.unsupportedParamsCombination( + ID, invalidVariants.toString(), + FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); + } + } + if (!xrefs.getGenes().isEmpty()) { + mightAddRegionFilter = false; + List invalidGenes = new ArrayList<>(); + Map geneRegionMap = cellBaseUtils.getGeneRegionMap(xrefs.getGenes(), false); + for (Map.Entry entry : geneRegionMap.entrySet()) { + if (VariantQueryUtils.intersectRegions(segregationChromosome, entry.getValue()) == null) { + invalidGenes.add(entry.getKey()); + } + } + if (!invalidGenes.isEmpty()) { + throw VariantQueryException.unsupportedParamsCombination( + GENE, invalidGenes.toString(), + FAMILY_SEGREGATION, query.getString(FAMILY_SEGREGATION.key())); + } + } + if (mightAddRegionFilter) { + query.put(REGION.key(), segregationChromosome); + query.put(PANEL_INTERSECTION.key(), true); + } + } + query.put(GENOTYPE.key(), gtFilter); + return segregationChromosome; } /** diff --git a/opencga-analysis/src/test/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtilsTest.java b/opencga-analysis/src/test/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtilsTest.java index e2ecb49c7ce..8a25bc5d70d 100644 --- a/opencga-analysis/src/test/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtilsTest.java +++ b/opencga-analysis/src/test/java/org/opencb/opencga/analysis/variant/manager/VariantCatalogQueryUtilsTest.java @@ -412,38 +412,41 @@ public void queryByFamilySegregation() throws Exception { @Test public void queryByFamilySegregationChromosomal() throws Exception { - Query query = queryUtils.parseQuery(new VariantQuery() + queryBySegregationChromosomal(new Query() + .append(FAMILY.key(), "f1") + .append(FAMILY_SEGREGATION.key(), "X_LINKED_RECESSIVE")); + } + + @Test + public void queryBySampleSegregationChromosomal() throws Exception { + queryBySegregationChromosomal(new Query(SAMPLE.key(), "sample3:X_LINKED_RECESSIVE")); + } + + public void queryBySegregationChromosomal(Query baseQuery) throws Exception { + Query query = queryUtils.parseQuery(new VariantQuery(baseQuery) .study("s1") .region("X:1-1000") .id("X:1:C:T") - .gene("BEX2") - .append(FAMILY.key(), "f1") - .append(FAMILY_SEGREGATION.key(), "X_LINKED_RECESSIVE"), null, cellBaseUtils, sessionId); + .gene("BEX2"), null, cellBaseUtils, sessionId); // Region untouched assertEquals("X:1-1000", query.getString(REGION.key())); - query = queryUtils.parseQuery(new VariantQuery() + query = queryUtils.parseQuery(new VariantQuery(baseQuery) .study("s1") - .id("X:1:C:T") - .append(FAMILY.key(), "f1") - .append(FAMILY_SEGREGATION.key(), "X_LINKED_RECESSIVE"), null, cellBaseUtils, sessionId); + .id("X:1:C:T"), null, cellBaseUtils, sessionId); // Region untouched, as filtering by variant IDs assertEquals(null, query.get(REGION.key())); - query = queryUtils.parseQuery(new VariantQuery() + query = queryUtils.parseQuery(new VariantQuery(baseQuery) .study("s1") - .append(PANEL.key(), myPanel.getId()) - .append(FAMILY.key(), "f1") - .append(FAMILY_SEGREGATION.key(), "X_LINKED_RECESSIVE"), null, cellBaseUtils, sessionId); + .append(PANEL.key(), myPanel.getId()), null, cellBaseUtils, sessionId); // Region untouched, as filtering by gene assertEquals(null, query.get(REGION.key())); assertEquals("BEX2", query.getString(GENE.key())); - query = queryUtils.parseQuery(new VariantQuery() + query = queryUtils.parseQuery(new VariantQuery(baseQuery) .study("s1") - .append(PANEL.key(), myPanelWithRegions.getId()) - .append(FAMILY.key(), "f1") - .append(FAMILY_SEGREGATION.key(), "X_LINKED_RECESSIVE"), null, cellBaseUtils, sessionId); + .append(PANEL.key(), myPanelWithRegions.getId()), null, cellBaseUtils, sessionId); // Region untouched, as filtering by gene System.out.println("query = " + query.toJson()); assertEquals("X:1-1000", query.getString(REGION.key())); diff --git a/opencga-storage/opencga-storage-core/src/main/java/org/opencb/opencga/storage/core/variant/adaptors/VariantQuery.java b/opencga-storage/opencga-storage-core/src/main/java/org/opencb/opencga/storage/core/variant/adaptors/VariantQuery.java index b7a01363f29..22c1648c3e0 100644 --- a/opencga-storage/opencga-storage-core/src/main/java/org/opencb/opencga/storage/core/variant/adaptors/VariantQuery.java +++ b/opencga-storage/opencga-storage-core/src/main/java/org/opencb/opencga/storage/core/variant/adaptors/VariantQuery.java @@ -7,8 +7,15 @@ import java.util.Arrays; import java.util.List; +import java.util.Map; public class VariantQuery extends Query { + public VariantQuery() { + } + + public VariantQuery(Map map) { + super(map); + } public VariantQuery id(String value) { put(VariantQueryParam.ID.key(), value); @@ -558,4 +565,9 @@ public String release() { public VariantQuery append(String key, Object value) { return (VariantQuery) super.append(key, value); } + + @Override + public VariantQuery appendAll(Map m) { + return (VariantQuery) super.appendAll(m); + } }