diff --git a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneService.java b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneService.java index 49c1ff9c9..09a0b7427 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneService.java +++ b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneService.java @@ -1,6 +1,5 @@ package uk.ac.ebi.atlas.experimentpage.markergenes; -import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.springframework.stereotype.Service; @@ -64,6 +63,7 @@ public ImmutableList getCellTypeMarkerGeneHeatmapData(String experim .filter(markerGene -> !markerGene.cellGroupValueWhereMarker().equalsIgnoreCase("Not available")) .collect(toImmutableList()); } + /** * @param experimentAccession - Id of the experiment * @param k - no of clusters @@ -73,4 +73,9 @@ public ImmutableList getCellTypeMarkerGeneHeatmapData(String experim public ImmutableList getMarkerGenesPerCluster(String experimentAccession, String k) { return ImmutableList.copyOf(markerGenesDao.getMarkerGenesWithAveragesPerCluster(experimentAccession, k)); } + + public Integer isMarkerGenesAvailableForTheInferredCellTypes(String experimentAccession, String cellGroupType) { + return markerGenesDao.getMarkerGenesForTheInferredCellTypes(experimentAccession, cellGroupType); + } + } diff --git a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDao.java b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDao.java index 62e2adb35..4de7c1c5e 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDao.java +++ b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDao.java @@ -9,14 +9,8 @@ @Repository public class MarkerGenesDao { - private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; static final String CELL_TYPE_ONTOLOGY_LABELS = "inferred cell type - ontology labels"; static final String CELL_TYPE_AUTHOR_LABELS = "inferred cell type - authors labels"; - - public MarkerGenesDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { - this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; - } - private static final String SELECT_MARKER_GENES_WITH_AVERAGES_PER_CLUSTER = "SELECT " + "g.experiment_accession, " + @@ -46,26 +40,6 @@ public MarkerGenesDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { "ORDER BY " + "m.marker_probability"; - public List getMarkerGenesWithAveragesPerCluster(String experimentAccession, String k) { - var namedParameters = - ImmutableMap.of( - "experiment_accession", experimentAccession, - "k", k); - - return namedParameterJdbcTemplate.query( - SELECT_MARKER_GENES_WITH_AVERAGES_PER_CLUSTER, - namedParameters, - (resultSet, rowNumber) -> MarkerGene.create( - resultSet.getString("gene_id"), - resultSet.getString("k_where_marker"), - resultSet.getString("cluster_id_where_marker"), - resultSet.getDouble("marker_p_value"), - resultSet.getString("cluster_id"), - resultSet.getDouble("median_expression"), - resultSet.getDouble("mean_expression"), - resultSet.getString("expression_unit"))); - } - private static final String SELECT_DISTINCT_KS_WITH_MARKER_GENES = "SELECT DISTINCT h.variable as k_where_marker " + "FROM scxa_cell_group_marker_genes m, scxa_cell_group h " + @@ -73,14 +47,6 @@ public List getMarkerGenesWithAveragesPerCluster(String experimentAc "h.experiment_accession = :experiment_accession AND m.marker_probability < 0.05 " + "ORDER BY k_where_marker ASC"; - public List getKsWithMarkerGenes(String experimentAccession) { - var namedParameters = ImmutableMap.of("experiment_accession", experimentAccession); - return namedParameterJdbcTemplate.queryForList( - SELECT_DISTINCT_KS_WITH_MARKER_GENES, - namedParameters, - String.class); - } - private static final String SELECT_MARKER_GENES_WITH_AVERAGES_PER_CELL_GROUP = "SELECT " + "g.experiment_accession, " + @@ -111,6 +77,81 @@ public List getKsWithMarkerGenes(String experimentAccession) { "ORDER BY " + "m.marker_probability "; + private static final String SELECT_MARKER_GENES_WITH_AVERAGES_PER_CELL_GROUP_ALL = + "SELECT " + + "g.experiment_accession, " + + "m.gene_id, " + + "g.variable AS cell_group_type, " + + "h.value AS cell_group_value_where_marker, " + + "g.value AS cell_group_value, " + + "m.marker_probability AS marker_p_value, " + + "s.mean_expression, " + + "s.median_expression, " + + "e.expression_unit " + + "FROM " + + "scxa_cell_group_marker_gene_stats s, " + + "scxa_cell_group_marker_genes m, " + + "scxa_cell_group g, " + + "scxa_cell_group h, " + + "experiment e " + + "WHERE " + + "s.cell_group_id = g.id AND " + + "s.marker_id = m.id AND " + + "m.cell_group_id = h.id AND " + + "g.experiment_accession = :experiment_accession AND " + + "m.marker_probability < 0.05 AND " + + "g.variable = :variable AND " + + "s.expression_type = 0 AND " + + "e.accession = g.experiment_accession " + + "ORDER BY " + + "m.marker_probability "; + + private static final String SELECT_MARKER_GENES_FOR_INFERRED_CELL_TYPES = + "SELECT count(m.gene_id) as marker_genes " + + "FROM " + + "scxa_cell_group_marker_genes m, " + + "scxa_cell_group h " + + "WHERE " + + "m.cell_group_id = h.id AND " + + "h.experiment_accession = :experiment_accession AND " + + "m.marker_probability < 0.05 AND " + + "h.variable= :variable " + + "LIMIT 1"; + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + public MarkerGenesDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } + + public List getMarkerGenesWithAveragesPerCluster(String experimentAccession, String k) { + var namedParameters = + ImmutableMap.of( + "experiment_accession", experimentAccession, + "k", k); + + return namedParameterJdbcTemplate.query( + SELECT_MARKER_GENES_WITH_AVERAGES_PER_CLUSTER, + namedParameters, + (resultSet, rowNumber) -> MarkerGene.create( + resultSet.getString("gene_id"), + resultSet.getString("k_where_marker"), + resultSet.getString("cluster_id_where_marker"), + resultSet.getDouble("marker_p_value"), + resultSet.getString("cluster_id"), + resultSet.getDouble("median_expression"), + resultSet.getDouble("mean_expression"), + resultSet.getString("expression_unit"))); + } + + public List getKsWithMarkerGenes(String experimentAccession) { + var namedParameters = ImmutableMap.of("experiment_accession", experimentAccession); + return namedParameterJdbcTemplate.queryForList( + SELECT_DISTINCT_KS_WITH_MARKER_GENES, + namedParameters, + String.class); + } + public List getCellTypeMarkerGenesOntologyLabels(String experimentAccession, ImmutableCollection cellGroupValues) { return getCellTypeMarkerGenes(experimentAccession, CELL_TYPE_ONTOLOGY_LABELS, cellGroupValues); @@ -148,34 +189,6 @@ public List getCellTypeMarkerGenes(String experiment_accession, resultSet.getString("expression_unit"))); } - private static final String SELECT_MARKER_GENES_WITH_AVERAGES_PER_CELL_GROUP_ALL = - "SELECT " + - "g.experiment_accession, " + - "m.gene_id, " + - "g.variable AS cell_group_type, " + - "h.value AS cell_group_value_where_marker, " + - "g.value AS cell_group_value, " + - "m.marker_probability AS marker_p_value, " + - "s.mean_expression, " + - "s.median_expression, " + - "e.expression_unit " + - "FROM " + - "scxa_cell_group_marker_gene_stats s, " + - "scxa_cell_group_marker_genes m, " + - "scxa_cell_group g, " + - "scxa_cell_group h, " + - "experiment e " + - "WHERE " + - "s.cell_group_id = g.id AND " + - "s.marker_id = m.id AND " + - "m.cell_group_id = h.id AND " + - "g.experiment_accession = :experiment_accession AND " + - "m.marker_probability < 0.05 AND " + - "g.variable = :variable AND " + - "s.expression_type = 0 AND " + - "e.accession = g.experiment_accession " + - "ORDER BY " + - "m.marker_probability "; public List getCellTypeMarkerGenes(String experiment_accession, String cellTypeVariable) { var namedParameters = @@ -196,4 +209,17 @@ public List getCellTypeMarkerGenes(String experiment_accession, resultSet.getDouble("mean_expression"), resultSet.getString("expression_unit"))); } + + public Integer getMarkerGenesForTheInferredCellTypes(String experimentAccession, String cellGroupType) { + var namedParameters = + ImmutableMap.of( + "experiment_accession", experimentAccession, + "variable", cellGroupType); + + return namedParameterJdbcTemplate.queryForObject( + SELECT_MARKER_GENES_FOR_INFERRED_CELL_TYPES, + namedParameters, + Integer.class); + + } } diff --git a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentService.java b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentService.java index 3dd3f1cfa..9852c7054 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentService.java +++ b/app/src/main/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentService.java @@ -7,12 +7,15 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import uk.ac.ebi.atlas.commons.readers.TsvStreamer; import uk.ac.ebi.atlas.download.ExperimentFileLocationService; import uk.ac.ebi.atlas.download.ExperimentFileType; import uk.ac.ebi.atlas.experimentpage.ExternallyAvailableContentService; import uk.ac.ebi.atlas.experimentpage.cellplot.CellPlotService; +import uk.ac.ebi.atlas.experimentpage.markergenes.MarkerGeneService; import uk.ac.ebi.atlas.experimentpage.metadata.CellMetadataService; import uk.ac.ebi.atlas.experimentpage.tsneplot.TSnePlotSettingsService; import uk.ac.ebi.atlas.model.download.ExternallyAvailableContent; @@ -29,6 +32,18 @@ @Service public class ExperimentPageContentService { + private static final String INFERRED_CELL_TYPE_ONTOLOGY_LABELS_FROM_DB = "inferred cell type - ontology labels"; + private static final String INFERRED_CELL_TYPE_AUTHORS_LABELS_FROM_DB = "Inferred cell type - authors labels"; + private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentPageContentService.class); + private static final ImmutableSet EXPERIMENTS_WITH_NO_ANATOMOGRAM = ImmutableSet.of( + "E-CURD-10", "E-CURD-11", "E-CURD-126", "E-CURD-135", + "E-GEOD-86618", "E-GEOD-114530", "E-GEOD-130473", + "E-HCAD-8", "E-HCAD-10", + "E-MTAB-6308", "E-MTAB-6653", "E-MTAB-7407", "E-MTAB-9067", "E-MTAB-10662", + "E-ANND-1", "E-ANND-2", "E-ANND-3", "E-ANND-4", "E-ANND-5"); + private static final String EXPERIMENT_TECHNOLOGY_TYPE_PREFIX = "smart-"; + private static final String INFERRED_CELL_TYPE_ONTOLOGY_LABELS_FROM_SOLR = "inferred_cell_type_-_ontology_labels"; + private static final String INFERRED_CELL_TYPE_AUTHORS_LABELS_FROM_SOLR = "inferred_cell_type_-_authors_labels"; private final ExperimentFileLocationService experimentFileLocationService; private final DataFileHub dataFileHub; private final TSnePlotSettingsService tsnePlotSettingsService; @@ -36,13 +51,7 @@ public class ExperimentPageContentService { private final OntologyAccessionsSearchService ontologyAccessionsSearchService; private final ExperimentTrader experimentTrader; private final CellPlotService cellPlotService; - - final static ImmutableSet EXPERIMENTS_WITH_NO_ANATOMOGRAM = ImmutableSet.of( - "E-CURD-10", "E-CURD-11", "E-CURD-126", "E-CURD-135", - "E-GEOD-86618", "E-GEOD-114530", "E-GEOD-130473", - "E-HCAD-8", "E-HCAD-10", - "E-MTAB-6308", "E-MTAB-6653", "E-MTAB-7407", "E-MTAB-9067", "E-MTAB-10662", - "E-ANND-1", "E-ANND-2", "E-ANND-3", "E-ANND-4", "E-ANND-5"); + private final MarkerGeneService markerGeneService; public ExperimentPageContentService(ExperimentFileLocationService experimentFileLocationService, DataFileHub dataFileHub, @@ -50,7 +59,7 @@ public ExperimentPageContentService(ExperimentFileLocationService experimentFile CellMetadataService cellMetadataService, OntologyAccessionsSearchService ontologyAccessionsSearchService, ExperimentTrader experimentTrader, - CellPlotService cellPlotService) { + CellPlotService cellPlotService, MarkerGeneService markerGeneService) { this.experimentFileLocationService = experimentFileLocationService; this.dataFileHub = dataFileHub; this.tsnePlotSettingsService = tsnePlotSettingsService; @@ -58,11 +67,17 @@ public ExperimentPageContentService(ExperimentFileLocationService experimentFile this.ontologyAccessionsSearchService = ontologyAccessionsSearchService; this.experimentTrader = experimentTrader; this.cellPlotService = cellPlotService; + this.markerGeneService = markerGeneService; + } + + + private static boolean isSmartExperiment(Collection technologyType) { + return technologyType.stream() + .anyMatch(type -> type.toLowerCase().startsWith(EXPERIMENT_TECHNOLOGY_TYPE_PREFIX)); } public JsonObject getTsnePlotData(String experimentAccession) { var result = new JsonObject(); - result.add( "ks", GSON.toJsonTree(tsnePlotSettingsService.getAvailableKs(experimentAccession))); @@ -82,6 +97,8 @@ public JsonObject getTsnePlotData(String experimentAccession) { result.add("metadata", getMetadata(experimentAccession)); + result.add("markerGeneMetadata", getMarkerGeneMetadata(getMetadata(experimentAccession), experimentAccession)); + var units = new JsonArray(); units.add("CPM"); result.add("units", units); @@ -164,12 +181,6 @@ public JsonArray getAnalysisMethods(String experimentAccession) { return result; } - public JsonArray getPerplexities(String experimentAccession) { - var perplexityArray = new JsonArray(); - tsnePlotSettingsService.getAvailablePerplexities(experimentAccession).forEach(perplexityArray::add); - return perplexityArray; - } - public JsonArray getMetadata(String experimentAccession) { var metadataArray = new JsonArray(); cellMetadataService @@ -184,7 +195,6 @@ public JsonArray getMetadata(String experimentAccession) { .map(x -> ImmutableMap.of("value", x, "label", StringUtil.snakeCaseToDisplayName(x))) .collect(Collectors.toSet()) .forEach(metadata -> metadataArray.add(GSON.toJsonTree(metadata))); - return metadataArray; } @@ -235,13 +245,56 @@ private JsonObject customContentTab(String tabType, String name, JsonObject prop return result; } - // Smart-Seq-like experiments will contain the substring “smart” in their technology types - private static boolean isSmartExperiment(Collection technologyType) { - return technologyType.stream() - .anyMatch(type -> type.toLowerCase().matches("smart" + "-(?:.*)")); + public ImmutableMap fetchDefaultPlotMethodAndParameterisation(String experimentAccession) { + return cellPlotService.fetchDefaultPlotMethodWithParameterisation(experimentAccession); } - public ImmutableMap fetchDefaultPlotMethodAndParameterisation(String experimentAccession){ - return cellPlotService.fetchDefaultPlotMethodWithParameterisation(experimentAccession); + public JsonArray getMarkerGeneMetadata(JsonArray metadata, String experimentAccession) { + JsonArray markerGenesArray = new JsonArray(); + + metadata.forEach(metadataObject -> { + JsonObject metaDataObject = getAsJsonObject(metadataObject); + + if (metaDataObject != null) { + String value = getValueAsString(metaDataObject); + + if (INFERRED_CELL_TYPE_ONTOLOGY_LABELS_FROM_SOLR.equals(value)) { + markerGenesArray.add(processMarkerGene(metaDataObject, experimentAccession, + INFERRED_CELL_TYPE_ONTOLOGY_LABELS_FROM_DB)); + } else if (INFERRED_CELL_TYPE_AUTHORS_LABELS_FROM_SOLR.equals(value)) { + markerGenesArray.add(processMarkerGene(metaDataObject, experimentAccession, + INFERRED_CELL_TYPE_AUTHORS_LABELS_FROM_DB)); + } else { + metaDataObject.addProperty("status", "false"); + markerGenesArray.add(metaDataObject); + } + } + }); + return markerGenesArray; + } + + private JsonObject processMarkerGene(JsonObject jsonObject, String experimentAccession, String dbLabel) { + boolean isAvailable = markerGeneService.isMarkerGenesAvailableForTheInferredCellTypes( + experimentAccession, dbLabel) > 0; + jsonObject.addProperty("status", isAvailable); + return jsonObject; + } + + private JsonObject getAsJsonObject(Object metadataItem) { + try { + return (JsonObject) metadataItem; + } catch (ClassCastException e) { + LOGGER.debug("Invalid metadata item: " + metadataItem); + return null; + } + } + + private String getValueAsString(JsonObject jsonObject) { + try { + return jsonObject.has("value") ? jsonObject.get("value").getAsString() : ""; + } catch (Exception e) { + LOGGER.debug("Error extracting value from JsonObject: " + jsonObject); + return ""; + } } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceIT.java b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceIT.java index 8a55d1e0b..d15697812 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceIT.java @@ -1,11 +1,7 @@ package uk.ac.ebi.atlas.experimentpage.markergenes; import com.google.common.collect.ImmutableSet; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; @@ -26,99 +22,113 @@ @ContextConfiguration(classes = TestConfig.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MarkerGeneServiceIT { - @Inject - private DataSource dataSource; - @Inject - private MarkerGenesDao markerGenesDao; - @Inject - private CellTypeSearchDao cellTypeSearchDao; - @Inject - private JdbcUtils jdbcTestUtils; - - private MarkerGeneService subject; - - @BeforeAll - void populateDatabaseTables() { - var populator = new ResourceDatabasePopulator(); - populator.addScripts( - new ClassPathResource("fixtures/experiment.sql"), - new ClassPathResource("fixtures/scxa_cell_group.sql"), - new ClassPathResource("fixtures/scxa_cell_group_membership.sql"), - new ClassPathResource("fixtures/scxa_cell_group_marker_genes.sql"), - new ClassPathResource("fixtures/scxa_cell_group_marker_gene_stats.sql")); - populator.execute(dataSource); - } - - @AfterAll - void cleanDatabaseTables() { - var populator = new ResourceDatabasePopulator(); - populator.addScripts( - new ClassPathResource("fixtures/scxa_cell_group_marker_gene_stats-delete.sql"), - new ClassPathResource("fixtures/scxa_cell_group_marker_genes-delete.sql"), - new ClassPathResource("fixtures/scxa_cell_group_membership-delete.sql"), - new ClassPathResource("fixtures/scxa_cell_group-delete.sql"), - new ClassPathResource("fixtures/experiment-delete.sql")); - populator.execute(dataSource); - } - - @BeforeEach - void setUp() { - subject = new MarkerGeneService(markerGenesDao, cellTypeSearchDao); - } + @Inject + private DataSource dataSource; + @Inject + private MarkerGenesDao markerGenesDao; + @Inject + private CellTypeSearchDao cellTypeSearchDao; + @Inject + private JdbcUtils jdbcTestUtils; + + private MarkerGeneService subject; + + @BeforeAll + void populateDatabaseTables() { + var populator = new ResourceDatabasePopulator(); + populator.addScripts( + new ClassPathResource("fixtures/experiment.sql"), + new ClassPathResource("fixtures/scxa_cell_group.sql"), + new ClassPathResource("fixtures/scxa_cell_group_membership.sql"), + new ClassPathResource("fixtures/scxa_cell_group_marker_genes.sql"), + new ClassPathResource("fixtures/scxa_cell_group_marker_gene_stats.sql")); + populator.execute(dataSource); + } + + @AfterAll + void cleanDatabaseTables() { + var populator = new ResourceDatabasePopulator(); + populator.addScripts( + new ClassPathResource("fixtures/scxa_cell_group_marker_gene_stats-delete.sql"), + new ClassPathResource("fixtures/scxa_cell_group_marker_genes-delete.sql"), + new ClassPathResource("fixtures/scxa_cell_group_membership-delete.sql"), + new ClassPathResource("fixtures/scxa_cell_group-delete.sql"), + new ClassPathResource("fixtures/experiment-delete.sql")); + populator.execute(dataSource); + } + + @BeforeEach + void setUp() { + subject = new MarkerGeneService(markerGenesDao, cellTypeSearchDao); + } @Test - void getMarkerGeneProfileForTheValidExperimentAccession() { - assertThat(subject.getCellTypeMarkerGeneProfile("E-EHCA-2", ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0000061"))) - .isNotEmpty(); - } - - @Test - void getEmptyMarkerGeneProfileForTheInvalidExperimentAccession() { - assertThat(subject.getCellTypeMarkerGeneProfile("FOO", ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0001264"))) - .isEmpty(); - } - - @Test - void getEmptyClusterMarkerGenesForTheInvalidExperimentAccession() { - assertThat(subject.getMarkerGenesPerCluster("FOO", "10")) - .isEmpty(); - } - - @Test - void getCellTypeMarkerGenesForMultipleOrganismParts(){ - assertThat( - subject.getCellTypeMarkerGeneProfile( - "FOO", - ImmutableSet.of( - "http://purl.obolibrary.org/obo/UBERON_0000061", - "http://purl.obolibrary.org/obo/UBERON_0001987"))) - .isEmpty(); - } - - @Test - void getClusterMarkerGeneForValidExperimentAccession() { - var experimentAccession = jdbcTestUtils.fetchRandomSingleCellExperimentAccessionWithMarkerGenes(); - var k = jdbcTestUtils.fetchRandomKWithMarkerGene(experimentAccession); - assertThat(subject.getMarkerGenesPerCluster(experimentAccession, k)) - .isNotEmpty(); - } - - @Test - void getCellTypeMarkerGenesForInvalidExperimentAccession() { - assertThat(subject.getCellTypeMarkerGeneProfile("FOO", ImmutableSet.of("skin"))) - .isEmpty(); - } - - @Test - void getCellTypesWithMarkerGenesForValidExperimentAccession() { - assertThat(subject.getCellTypesWithMarkerGenes("E-MTAB-5061", "inferred cell type - ontology labels")) - .isNotEmpty(); - } - - @Test - void getCellTypeMarkerGeneHeatmapForValidExperimentAccesion() { - assertThat(subject.getCellTypeMarkerGeneHeatmapData( - "E-MTAB-5061", "inferred cell type - ontology labels")) - .isNotEmpty(); - } + void getMarkerGeneProfileForTheValidExperimentAccession() { + assertThat(subject.getCellTypeMarkerGeneProfile("E-EHCA-2", ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0000061"))) + .isNotEmpty(); + } + + @Test + void getEmptyMarkerGeneProfileForTheInvalidExperimentAccession() { + assertThat(subject.getCellTypeMarkerGeneProfile("FOO", ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0001264"))) + .isEmpty(); + } + + @Test + void getEmptyClusterMarkerGenesForTheInvalidExperimentAccession() { + assertThat(subject.getMarkerGenesPerCluster("FOO", "10")) + .isEmpty(); + } + + @Test + void getCellTypeMarkerGenesForMultipleOrganismParts() { + assertThat( + subject.getCellTypeMarkerGeneProfile( + "FOO", + ImmutableSet.of( + "http://purl.obolibrary.org/obo/UBERON_0000061", + "http://purl.obolibrary.org/obo/UBERON_0001987"))) + .isEmpty(); + } + + @Test + void getClusterMarkerGeneForValidExperimentAccession() { + var experimentAccession = jdbcTestUtils.fetchRandomSingleCellExperimentAccessionWithMarkerGenes(); + var k = jdbcTestUtils.fetchRandomKWithMarkerGene(experimentAccession); + assertThat(subject.getMarkerGenesPerCluster(experimentAccession, k)) + .isNotEmpty(); + } + + @Test + void getCellTypeMarkerGenesForInvalidExperimentAccession() { + assertThat(subject.getCellTypeMarkerGeneProfile("FOO", ImmutableSet.of("skin"))) + .isEmpty(); + } + + @Test + void getCellTypesWithMarkerGenesForValidExperimentAccession() { + assertThat(subject.getCellTypesWithMarkerGenes("E-MTAB-5061", "inferred cell type - ontology labels")) + .isNotEmpty(); + } + + @Test + void getCellTypeMarkerGeneHeatmapForValidExperimentAccession() { + assertThat(subject.getCellTypeMarkerGeneHeatmapData( + "E-MTAB-5061", "inferred cell type - ontology labels")) + .isNotEmpty(); + } + + @Test + void getMarkerGenesCountForTheInferredCellTypesOntologyLabel() { + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes( + "E-MTAB-5061", "inferred cell type - ontology labels")) + .isGreaterThan(0); + } + + @Test + void getMarkerGenesCountForTheInferredCellTypesAuthorsLabel() { + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes( + "E-EHCA-2", "inferred cell type - authors labels")) + .isGreaterThan(0); + } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceTest.java b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceTest.java index a23abd2b0..eedecf2f1 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceTest.java +++ b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGeneServiceTest.java @@ -67,6 +67,53 @@ void returnEmptyCellTypeMarkerGeneProfileIfBothOntologyAndAuthorsLabelsDoesNotHa assertThat(subject.getCellTypeMarkerGeneProfile("E-EHCA-2", ImmutableSet.of("skin"))).isEmpty(); } + @Test + void getMarkerGenesCountGreaterThanZero_IfTheMarkerGenesExistForTheInferredCellTypeOntologyLabels() { + when(markerGenesDaoMock.getMarkerGenesForTheInferredCellTypes("E-EHCA-2", + "inferred cell type - ontology labels")) + .thenReturn(1); + + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes("E-EHCA-2", + "inferred cell type - ontology labels")) + .isGreaterThan(0); + } + + @Test + void getMarkerGenesCountGreaterThanZero_IfTheMarkerGenesExistForTheInferredCellTypeAuthorsLabels() { + when(markerGenesDaoMock.getMarkerGenesForTheInferredCellTypes( + "E-EHCA-2", + "inferred cell type - authors labels")) + .thenReturn(1); + + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes( + "E-EHCA-2", + "inferred cell type - authors labels")) + .isEqualTo(1); + } + + @Test + void getMarkerGenesCountZero_IfTheMarkerGenesDoesNotExistForTheOntologyLabels() { + when(markerGenesDaoMock.getMarkerGenesForTheInferredCellTypes( + "E-EHCA-2", + "inferred cell type - ontology labels")) + .thenReturn(0); + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes( + "E-EHCA-2", + "inferred cell type - ontology labels")) + .isZero(); + } + + @Test + void getMarkerGenesCountZero_IfTheMarkerGenesDoesNotExistForTheAuthorsLabels() { + when(markerGenesDaoMock.getMarkerGenesForTheInferredCellTypes("E-EHCA-2", + "inferred cell type - Authors labels")) + .thenReturn(0); + assertThat(subject.isMarkerGenesAvailableForTheInferredCellTypes( + "E-EHCA-2", + "inferred cell type - Authors labels")) + .isZero(); + } + private List mockTestData() { return ImmutableList.of( MarkerGene.create("1", "inferred cell type", diff --git a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDaoIT.java b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDaoIT.java index e4438c9fe..2a0661a57 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDaoIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/markergenes/MarkerGenesDaoIT.java @@ -29,18 +29,14 @@ @ContextConfiguration(classes = TestConfig.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MarkerGenesDaoIT { + private static final String EXPERIMENT_ACCESSION_WITH_MARKER_GENES = "E-GEOD-99058"; + private static final String CELL_GROUP_EXPERIMENT_ACCESSION_WITH_MARKER_GENES = "E-EHCA-2"; @Inject private DataSource dataSource; - @Inject private NamedParameterJdbcTemplate namedParameterJdbcTemplate; - @Inject private JdbcUtils jdbcTestUtils; - - private static final String EXPERIMENT_ACCESSION_WITH_MARKER_GENES = "E-GEOD-99058"; - private static final String CELL_GROUP_EXPERIMENT_ACCESSION_WITH_MARKER_GENES = "E-EHCA-2"; - private MarkerGenesDao subject; @BeforeAll @@ -131,4 +127,28 @@ void shouldGetMarkerGenesHeatmapDataForTheGivenCellGroupAndCellType() { .allMatch(markerGene -> markerGene.cellGroupType().equals("inferred cell type - ontology labels")); } + + @Test + void getMarkerGenesCount_IfTheMarkerGenesExistForTheOntologyLabels() { + var markerGenesRecordsCount = subject.getMarkerGenesForTheInferredCellTypes( + "E-MTAB-5061", "inferred cell type - ontology labels"); + + assertThat(markerGenesRecordsCount).isGreaterThan(0); + } + + @Test + void getMarkerGenesCount_IfTheMarkerGenesExistForTheAuthorsLabels() { + var markerGenesRecordsCount = subject.getMarkerGenesForTheInferredCellTypes( + "E-EHCA-2", "inferred cell type - authors labels"); + + assertThat(markerGenesRecordsCount).isGreaterThan(0); + } + + @Test + void whenMarkerGenesDoesNotExistForTheAuthorsOrOntologyLabels_thenMarkerGenesCountShouldBeZero() { + var markerGenesRecordsCount = subject.getMarkerGenesForTheInferredCellTypes( + "foo", "inferred cell type - authors labels"); + + assertThat(markerGenesRecordsCount).isZero(); + } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceIT.java b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceIT.java index 40c083db4..3276547d3 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceIT.java @@ -17,6 +17,7 @@ import uk.ac.ebi.atlas.configuration.TestConfig; import uk.ac.ebi.atlas.download.ExperimentFileLocationService; import uk.ac.ebi.atlas.experimentpage.cellplot.CellPlotService; +import uk.ac.ebi.atlas.experimentpage.markergenes.MarkerGeneService; import uk.ac.ebi.atlas.experimentpage.tsneplot.TSnePlotSettingsService; import uk.ac.ebi.atlas.experimentpage.metadata.CellMetadataService; import uk.ac.ebi.atlas.resource.DataFileHub; @@ -62,6 +63,9 @@ class ExperimentPageContentServiceIT { @Inject private CellPlotService cellPlotService; + @Inject + private MarkerGeneService markerGeneService; + private ExperimentPageContentService subject; @BeforeAll @@ -101,7 +105,8 @@ void setUp() { cellMetadataService, ontologyAccessionsSearchService, experimentTrader, - cellPlotService); + cellPlotService, + markerGeneService); } @Test diff --git a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceTest.java b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceTest.java index 71c8dc714..1a0ec36fc 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceTest.java +++ b/app/src/test/java/uk/ac/ebi/atlas/experimentpage/tabs/ExperimentPageContentServiceTest.java @@ -16,6 +16,7 @@ import uk.ac.ebi.atlas.download.ExperimentFileType; import uk.ac.ebi.atlas.download.IconType; import uk.ac.ebi.atlas.experimentpage.cellplot.CellPlotService; +import uk.ac.ebi.atlas.experimentpage.markergenes.MarkerGeneService; import uk.ac.ebi.atlas.experimentpage.metadata.CellMetadataService; import uk.ac.ebi.atlas.experimentpage.tsneplot.TSnePlotSettingsService; import uk.ac.ebi.atlas.experiments.ExperimentBuilder; @@ -29,8 +30,8 @@ import java.util.concurrent.ThreadLocalRandom; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -import static uk.ac.ebi.atlas.experimentpage.tabs.ExperimentPageContentService.EXPERIMENTS_WITH_NO_ANATOMOGRAM; import static uk.ac.ebi.atlas.testutils.RandomDataTestUtils.generateRandomExperimentAccession; @ExtendWith(MockitoExtension.class) @@ -43,32 +44,23 @@ class ExperimentPageContentServiceTest { private static final String EXPERIMENT_FILES_URI_TEMPLATE = "experiment/abc/download?fileType=xyz&accessKey=efg"; private static final String EXPERIMENT_ACCESSION = generateRandomExperimentAccession(); - private static final String NON_ANATOMOGRAM_EXPERIMENT_ACCESSION = - EXPERIMENTS_WITH_NO_ANATOMOGRAM.asList().get(RNG.nextInt(EXPERIMENTS_WITH_NO_ANATOMOGRAM.size())); - + private final JsonObject tpmsDownloadJsonObject = new JsonObject(); @Mock private ExperimentFileLocationService experimentFileLocationServiceMock; - @Mock private DataFileHub dataFileHubMock; - @Mock private TSnePlotSettingsService tsnePlotSettingsServiceMock; - @Mock private CellMetadataService cellMetadataServiceMock; - @Mock private OntologyAccessionsSearchService ontologyAccessionsSearchService; - @Mock private ExperimentTrader experimentTraderMock; - @Mock private CellPlotService cellPlotServiceMock; - - private final JsonObject tpmsDownloadJsonObject = new JsonObject(); - + @Mock + private MarkerGeneService markerGeneServiceMock; private ExperimentPageContentService subject; @BeforeEach @@ -115,17 +107,17 @@ void setUp() { "") ).thenReturn(URI.create(EXPERIMENT_FILES_ARCHIVE_URI_TEMPLATE)); - when(tsnePlotSettingsServiceMock.getAvailableKs(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION)) + when(tsnePlotSettingsServiceMock.getAvailableKs(anyString())) .thenReturn(ImmutableList.of(1, 2, 3)); - when(tsnePlotSettingsServiceMock.getKsWithMarkerGenes(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION)) + when(tsnePlotSettingsServiceMock.getKsWithMarkerGenes(anyString())) .thenReturn(ImmutableList.of("1", "2")); - when(tsnePlotSettingsServiceMock.getExpectedClusters(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION)) + when(tsnePlotSettingsServiceMock.getExpectedClusters(anyString())) .thenReturn(Optional.of(1)); - when(tsnePlotSettingsServiceMock.getAvailablePerplexities(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION)) + when(tsnePlotSettingsServiceMock.getAvailablePerplexities(anyString())) .thenReturn(ImmutableList.of(1, 2, 3)); - when(cellMetadataServiceMock.getMetadataTypes(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION)) - .thenReturn(ImmutableSet.of("foo")); - when(cellMetadataServiceMock.getMetadataValuesForGivenType(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION, "foo")) + when(cellMetadataServiceMock.getMetadataTypes(anyString())) + .thenReturn(ImmutableSet.of("foo", "bar", "foo bar")); + when(cellMetadataServiceMock.getMetadataValuesForGivenType(anyString(), anyString())) .thenReturn(ImmutableMap.of()); subject = new ExperimentPageContentService( @@ -135,7 +127,8 @@ void setUp() { cellMetadataServiceMock, ontologyAccessionsSearchService, experimentTraderMock, - cellPlotServiceMock); + cellPlotServiceMock, + markerGeneServiceMock); tpmsDownloadJsonObject.addProperty("url", EXPERIMENT_FILES_ARCHIVE_URI_TEMPLATE); tpmsDownloadJsonObject.addProperty("type", IconType.TSV.getName()); @@ -150,7 +143,7 @@ void smartExperimentsHaveTPMDownloadFiles() { .withTechnologyType(ImmutableList.of("Smart-Seq", "10xV1")) .build(); - when(experimentTraderMock.getExperiment(EXPERIMENT_ACCESSION,"")).thenReturn(experiment); + when(experimentTraderMock.getExperiment(EXPERIMENT_ACCESSION, "")).thenReturn(experiment); var result = subject.getDownloads(EXPERIMENT_ACCESSION, ""); assertThat(result) @@ -173,7 +166,7 @@ void nonSmartExperimentsDoesNotHaveTPMDownloadFiles() { .withTechnologyType(ImmutableList.of("10xV1")) .build(); - when(experimentTraderMock.getExperiment(EXPERIMENT_ACCESSION,"")).thenReturn(experiment); + when(experimentTraderMock.getExperiment(EXPERIMENT_ACCESSION, "")).thenReturn(experiment); var result = subject.getDownloads(EXPERIMENT_ACCESSION, ""); assertThat(result) @@ -191,24 +184,24 @@ void nonSmartExperimentsDoesNotHaveTPMDownloadFiles() { @Test void anatomogramDoesNotExistForValidExperiment() { - var result = this.subject.getTsnePlotData(NON_ANATOMOGRAM_EXPERIMENT_ACCESSION); - + var result = this.subject.getTsnePlotData("E-CURD-10"); assertThat(result.getAsJsonObject("anatomogram").size()).isEqualTo(0); } @Test - void getEmptyDefaultPlotMethodAndParamsForTheInvalidExperiment(){ - when(cellPlotServiceMock.fetchDefaultPlotMethodWithParameterisation("FooBar")) + void givenInvalidExperiment_thenReturnsEmptyDefaultPlotMethodAndParams() { + String invalidExperimentAccession = "FooBar"; + when(cellPlotServiceMock.fetchDefaultPlotMethodWithParameterisation(invalidExperimentAccession)) .thenReturn(ImmutableMap.of()); - assertThat(subject.fetchDefaultPlotMethodAndParameterisation("FooBar")).isEmpty(); + assertThat(subject.fetchDefaultPlotMethodAndParameterisation(invalidExperimentAccession)).isEmpty(); } @Test - void getEmptyDefaultPlotMethodAndParamsForTheValidExperiment(){ + void getEmptyDefaultPlotMethodAndParamsForTheValidExperiment() { when(cellPlotServiceMock.fetchDefaultPlotMethodWithParameterisation("E-CURD-4")) - .thenReturn(ImmutableMap.of("umap",new Gson().fromJson("{\"n_neighbors\":100}",JsonObject.class), - "tsne",new Gson().fromJson("{\"perplexity\":50}",JsonObject.class))); + .thenReturn(ImmutableMap.of("umap", new Gson().fromJson("{\"n_neighbors\":100}", JsonObject.class), + "tsne", new Gson().fromJson("{\"perplexity\":50}", JsonObject.class))); assertThat(subject.fetchDefaultPlotMethodAndParameterisation("E-CURD-4")).isNotEmpty(); }