Skip to content

Commit

Permalink
Austenem/CAT-980 Fix EPIC Bulk Data Transfer sections (#3582)
Browse files Browse the repository at this point in the history
* update bulk data panel processing

* add tests and updated dataset types

* add changelog

* update variable names for clarity
  • Loading branch information
austenem authored Oct 29, 2024
1 parent 6b5314a commit a296432
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-fix-epic-bdt-section.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix EPIC Bulk Data Transfer section tabs and prevent these from crashing the page.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function getEntityLabel({ entity, sampleCategoryCounts }: getEntityLabelProps) {
return entity.sample_category;
}
if (isDataset(entity)) {
return entity.assay_display_name;
return entity.assay_display_name[0];
}
return entity.entity_type;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { processDatasetLabel } from './hooks';

const hits: {
_source: {
assay_display_name: string[];
hubmap_id: string;
pipeline?: string;
status: string;
};
}[] = [
{
_source: {
assay_display_name: ['PAS Stained Microscopy [Kaggle-1 Glomerulus Segmentation]'],
hubmap_id: 'HBM739.DJFC.689',
pipeline: 'Kaggle-1 Glomerulus Segmentation',
status: 'QA',
},
},
{
_source: {
assay_display_name: ['Segmentation Mask'],
hubmap_id: 'HBM984.FHHM.241',
status: 'Published',
},
},
];

it('checks if bulk data transfer panels are labeled correctly', () => {
const labels = hits.map((hit) => processDatasetLabel(hit._source, hits));
expect(labels).toEqual(['Kaggle-1 Glomerulus Segmentation', 'Segmentation Mask']);
});

const hitsWithDuplicates = [
...hits,
{
_source: {
assay_display_name: ['PAS Stained Microscopy [Kaggle-1 Glomerulus Segmentation]'],
hubmap_id: 'HBM739.DJFC.675',
pipeline: 'Kaggle-1 Glomerulus Segmentation',
status: 'QA',
},
},
{
_source: {
assay_display_name: ['Segmentation Mask'],
hubmap_id: 'HBM984.FHHM.240',
status: 'QA',
},
},
{
_source: {
assay_display_name: ['Visium (no probes)'],
hubmap_id: 'HBM878.KLWL.738',
pipeline: 'Visium (no probes)',
status: 'QA',
},
},
];

it('checks if bulk data transfer panels with duplicate analyses are labeled correctly', () => {
const labels = hitsWithDuplicates.map((hit) => processDatasetLabel(hit._source, hitsWithDuplicates));
expect(labels).toEqual([
'Kaggle-1 Glomerulus Segmentation (QA) [HBM739.DJFC.689]',
'Segmentation Mask (Published)',
'Kaggle-1 Glomerulus Segmentation (QA) [HBM739.DJFC.675]',
'Segmentation Mask (QA)',
'Visium (no probes)',
]);
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { excludeComponentDatasetsClause, getIDsQuery } from 'js/helpers/queries'
import { useSearchHits } from 'js/hooks/useSearchData';
import { useProcessedDatasets, type ProcessedDatasetInfo } from 'js/pages/Dataset/hooks';
import { ComponentType } from 'react';
import { SearchHit } from '@elastic/elasticsearch/lib/api/types';
import { nodeIcons } from '../../DatasetRelationships/nodeTypes';

export type ProcessedDatasetDetails = ProcessedDatasetInfo &
Expand Down Expand Up @@ -68,18 +67,28 @@ export function useProcessedDatasetDetails(uuid: string) {
return { datasetDetails, isLoading };
}

function processDatasetLabel(dataset: ProcessedDatasetInfo, hits: Required<SearchHit<ProcessedDatasetInfo>>[]) {
const multipleHitsWithSamePipeline = hits.filter((h) => h._source.pipeline === dataset.pipeline).length > 1;
const multipleHitsWithSamePipelineAndStatus =
multipleHitsWithSamePipeline &&
hits.filter((h) => h._source.pipeline === dataset.pipeline && h._source.status === dataset.status).length > 1;
if (multipleHitsWithSamePipelineAndStatus) {
return `${dataset.pipeline} (${dataset.status}) [${dataset.hubmap_id}]`;
export function processDatasetLabel(
dataset: Pick<ProcessedDatasetInfo, 'assay_display_name' | 'pipeline' | 'status' | 'hubmap_id'>,
hits: { _source: Pick<ProcessedDatasetInfo, 'assay_display_name' | 'pipeline' | 'status'> }[],
) {
const label = dataset.pipeline ?? dataset.assay_display_name[0];
const hasMultipleHitsWithSameLabel =
hits.filter((h) => (h._source.pipeline ?? h._source.assay_display_name[0]) === label).length > 1;

const hasMultipleHitsWithSameLabelAndStatus =
hasMultipleHitsWithSameLabel &&
hits.filter(
(h) => (h._source.pipeline ?? h._source.assay_display_name[0]) === label && h._source.status === dataset.status,
).length > 1;

if (hasMultipleHitsWithSameLabelAndStatus) {
return `${label} (${dataset.status}) [${dataset.hubmap_id}]`;
}
if (multipleHitsWithSamePipeline) {
return `${dataset.pipeline} (${dataset.status})`;
if (hasMultipleHitsWithSameLabel) {
return `${label} (${dataset.status})`;
}
return dataset.pipeline;

return label;
}

export function useProcessedDatasetTabs(): { label: string; uuid: string; icon: ComponentType | undefined }[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const testDatasets: {
_index: string;
_score: number;
_source: {
assay_display_name: string;
assay_display_name: string[];
created_timestamp: number;
creation_action: CreationAction;
entity_type: string;
Expand All @@ -24,7 +24,7 @@ const testDatasets: {
_index: 'hm_prod_consortium_portal',
_score: 1,
_source: {
assay_display_name: 'CODEX [Cytokit + SPRM]',
assay_display_name: ['CODEX [Cytokit + SPRM]'],
created_timestamp: 1688952984040,
creation_action: 'Central Process',
entity_type: 'Dataset',
Expand All @@ -41,7 +41,7 @@ const testDatasets: {
_index: 'hm_prod_consortium_portal',
_score: 1,
_source: {
assay_display_name: 'CODEX [Cytokit + SPRM]',
assay_display_name: ['CODEX [Cytokit + SPRM]'],
created_timestamp: 1689198074733,
creation_action: 'Central Process',
entity_type: 'Dataset',
Expand All @@ -58,7 +58,7 @@ const testDatasets: {
_index: 'hm_prod_consortium_portal',
_score: 1,
_source: {
assay_display_name: 'External (Segmentation Mask)',
assay_display_name: ['External (Segmentation Mask)'],
created_timestamp: 1689198074733,
creation_action: 'External Process',
entity_type: 'Dataset',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function useSortedSearchHits(datasets: ReturnType<typeof useProcessedData
* @returns Text for the analyses label, and additional text for each analysis and its count.
*/
export function useAnalysesCountInfo(datasets: Pick<ProcessedDatasetInfo, 'pipeline' | 'assay_display_name'>[]) {
const analyses = datasets.map((dataset) => dataset.pipeline ?? dataset.assay_display_name);
const analyses = datasets.map((dataset) => dataset.pipeline ?? dataset.assay_display_name[0]);
const analysesCount = analyses.reduce(
(acc, analysis) => {
acc[analysis] = (acc[analysis] || 0) + 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function MultiTileStack({ datasets, title }: { datasets: MultiAssayEntity[]; tit
id={hubmap_id}
invertColors={uuid === currentEntityUUID}
entityData={{
mapped_data_types: [assay_display_name],
mapped_data_types: [assay_display_name[0]],
origin_samples,
origin_samples_unique_mapped_organs,
last_modified_timestamp,
Expand Down
4 changes: 2 additions & 2 deletions context/app/static/js/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ export type CreationAction =
export interface Dataset extends Entity {
entity_type: 'Dataset';
processing: 'raw' | 'processed';
pipeline: string;
assay_display_name: string;
pipeline?: string;
assay_display_name: string[];
is_component?: boolean;
assay_modality: 'single' | 'multiple';
donor: Donor;
Expand Down

0 comments on commit a296432

Please sign in to comment.