Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/make the inferred cell type options dynamic shown or disabled in marker gene heatmap dropdown menu #482

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8e7177a
Fetch marker gene id with experiment accession from the DB
upendrakumbham Oct 21, 2024
9b74beb
Merge branch 'develop' into make-the-inferred-cell-type-options-dynam…
upendrakumbham Oct 21, 2024
4ab3665
Fix broken tests
upendrakumbham Oct 24, 2024
2e3cb5d
Update SQL query
upendrakumbham Oct 24, 2024
0ba7088
Add a method to filter conditional meta data for marker genes tab
upendrakumbham Nov 6, 2024
8ada971
Add a private method to filter data to generate markergene metadata i…
upendrakumbham Nov 13, 2024
2539249
Merge branch 'develop' into bugfix/make-the-inferred-cell-type-option…
upendrakumbham Nov 13, 2024
9f351b1
Add a DAO tests
upendrakumbham Nov 13, 2024
5c1fccc
Fix broken tests
upendrakumbham Nov 14, 2024
918127c
Add Service layer tests
upendrakumbham Nov 14, 2024
9f9fa67
Add service integration tests
upendrakumbham Nov 15, 2024
5ff7093
Improve getMarkerGeneMetadata method
upendrakumbham Nov 15, 2024
47be475
Add generalised unit tests as per review comment
upendrakumbham Nov 27, 2024
f3c04f2
Fix review comments - remove regx, remove unnecessary code and code i…
upendrakumbham Nov 28, 2024
11c992b
Update test method name
upendrakumbham Nov 29, 2024
061dd39
Improve code
upendrakumbham Nov 29, 2024
2bcfce7
Merge branch 'develop' into bugfix/make-the-inferred-cell-type-option…
upendrakumbham Nov 29, 2024
7bc29be
Improve code
upendrakumbham Nov 29, 2024
cffd5c9
Update test
upendrakumbham Nov 29, 2024
cade7ec
Code cleanup and improvements
upendrakumbham Dec 4, 2024
1ad1bcd
Remove unused methods
upendrakumbham Dec 4, 2024
a4575ab
Replace Sys err with logger
upendrakumbham Dec 4, 2024
6c3a201
Refactor variables names
upendrakumbham Dec 4, 2024
da7062e
Fix broken test
upendrakumbham Dec 5, 2024
d353670
Improve test method name
upendrakumbham Dec 5, 2024
d5bd597
Rename test method
upendrakumbham Dec 5, 2024
72f2036
Update code
upendrakumbham Dec 5, 2024
6adbc57
Update access modifier
upendrakumbham Dec 5, 2024
cd347f2
Update variable name
upendrakumbham Dec 5, 2024
5686849
Fix broken test
upendrakumbham Dec 5, 2024
d1d487f
Rename test methods
upendrakumbham Dec 6, 2024
6bd29a6
Merge branch 'develop' into bugfix/make-the-inferred-cell-type-option…
upendrakumbham Dec 9, 2024
98eefdb
Update tests
upendrakumbham Dec 9, 2024
19131a3
Update SQL queries indentation format like previous format
upendrakumbham Dec 13, 2024
a210be5
Merge branch 'develop' into bugfix/make-the-inferred-cell-type-option…
upendrakumbham Dec 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -64,6 +63,7 @@ public ImmutableList<MarkerGene> getCellTypeMarkerGeneHeatmapData(String experim
.filter(markerGene -> !markerGene.cellGroupValueWhereMarker().equalsIgnoreCase("Not available"))
.collect(toImmutableList());
}

/**
* @param experimentAccession - Id of the experiment
* @param k - no of clusters
Expand All @@ -73,4 +73,9 @@ public ImmutableList<MarkerGene> getCellTypeMarkerGeneHeatmapData(String experim
public ImmutableList<MarkerGene> getMarkerGenesPerCluster(String experimentAccession, String k) {
return ImmutableList.copyOf(markerGenesDao.getMarkerGenesWithAveragesPerCluster(experimentAccession, k));
}

public Integer isMarkerGenesAvailableForTheInferredCellTypes(String experimentAccession, String cellGroupType) {
return markerGenesDao.getMarkerGenesForTheInferredCellTypes(experimentAccession, cellGroupType);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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, " +
Expand Down Expand Up @@ -46,41 +40,13 @@ public MarkerGenesDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
"ORDER BY " +
"m.marker_probability";

public List<MarkerGene> 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 " +
"WHERE m.cell_group_id = h.id AND " +
"h.experiment_accession = :experiment_accession AND m.marker_probability < 0.05 " +
"ORDER BY k_where_marker ASC";

public List<String> 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, " +
Expand Down Expand Up @@ -111,6 +77,81 @@ public List<String> 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<MarkerGene> 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<String> getKsWithMarkerGenes(String experimentAccession) {
var namedParameters = ImmutableMap.of("experiment_accession", experimentAccession);
return namedParameterJdbcTemplate.queryForList(
SELECT_DISTINCT_KS_WITH_MARKER_GENES,
namedParameters,
String.class);
}

public List<MarkerGene> getCellTypeMarkerGenesOntologyLabels(String experimentAccession,
ImmutableCollection<String> cellGroupValues) {
return getCellTypeMarkerGenes(experimentAccession, CELL_TYPE_ONTOLOGY_LABELS, cellGroupValues);
Expand Down Expand Up @@ -148,34 +189,6 @@ public List<MarkerGene> 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<MarkerGene> getCellTypeMarkerGenes(String experiment_accession,
String cellTypeVariable) {
var namedParameters =
Expand All @@ -196,4 +209,17 @@ public List<MarkerGene> 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);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,40 +32,52 @@

@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<String> 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;
private final CellMetadataService cellMetadataService;
private final OntologyAccessionsSearchService ontologyAccessionsSearchService;
private final ExperimentTrader experimentTrader;
private final CellPlotService cellPlotService;

final static ImmutableSet<String> 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,
TSnePlotSettingsService tsnePlotSettingsService,
CellMetadataService cellMetadataService,
OntologyAccessionsSearchService ontologyAccessionsSearchService,
ExperimentTrader experimentTrader,
CellPlotService cellPlotService) {
CellPlotService cellPlotService, MarkerGeneService markerGeneService) {
upendrakumbham marked this conversation as resolved.
Show resolved Hide resolved
this.experimentFileLocationService = experimentFileLocationService;
this.dataFileHub = dataFileHub;
this.tsnePlotSettingsService = tsnePlotSettingsService;
this.cellMetadataService = cellMetadataService;
this.ontologyAccessionsSearchService = ontologyAccessionsSearchService;
this.experimentTrader = experimentTrader;
this.cellPlotService = cellPlotService;
this.markerGeneService = markerGeneService;
}


private static boolean isSmartExperiment(Collection<String> 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)));
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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;
}

Expand Down Expand Up @@ -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<String> 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 "";
}
}
}
Loading
Loading