Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions packages/oncoprintjs/src/js/oncoprinttrackinfoview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ export default class OncoprintTrackInfoView {
let formattedPercent = '';

if (isNaN(float)) {
formattedPercent = 'N/P';
suffix = ''; // we don't want any suffix in this case
// Non-numeric info (the "N/P" sentinel, or a warning glyph)
// is shown verbatim rather than coerced to a percentage.
formattedPercent = text;
suffix = '';
} else if (isNumber(float)) {
formattedPercent =
float < 1 && float > 0
Expand Down
14 changes: 14 additions & 0 deletions src/shared/components/oncoprint/DeltaUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,9 @@ export function transitionHeatmapTrack(
nextProps.caseLinkOutInTooltips
),
track_info: nextSpec.info || '',
$track_info_tooltip_elt: nextSpec.infoTooltip
? $('<div>' + nextSpec.infoTooltip + '</div>')
: undefined,
onSortDirectionChange: nextProps.onTrackSortDirectionChange,
expansion_of: expansionParentKey
? trackSpecKeyToTrackId[expansionParentKey]
Expand Down Expand Up @@ -1627,6 +1630,14 @@ export function transitionHeatmapTrack(
if (nextSpec.info !== prevSpec.info && nextSpec.info !== undefined) {
oncoprint.setTrackInfo(trackId, nextSpec.info);
}
if (nextSpec.infoTooltip !== prevSpec.infoTooltip) {
oncoprint.setTrackInfoTooltip(
trackId,
nextSpec.infoTooltip
? $('<div>' + nextSpec.infoTooltip + '</div>')
: undefined
);
}
if (
nextSpec.movable !== prevSpec.movable &&
nextSpec.movable !== undefined
Expand Down Expand Up @@ -1733,6 +1744,9 @@ export function transitionCategoricalTrack(
nextProps.caseLinkOutInTooltips
),
track_info: nextSpec.info || '',
$track_info_tooltip_elt: nextSpec.infoTooltip
? $('<div>' + nextSpec.infoTooltip + '</div>')
: undefined,
onSortDirectionChange: nextProps.onTrackSortDirectionChange,
};
const newTrackId = oncoprint.addTracks([trackParams])[0];
Expand Down
2 changes: 2 additions & 0 deletions src/shared/components/oncoprint/Oncoprint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ export interface IHeatmapTrackSpec extends IBaseHeatmapTrackSpec {
data: IBaseHeatmapTrackDatum[]; // can be IGeneHeatmapTrackDatum or IGenericAssayHeatmapTrackDatum
naLegendLabel?: string;
info?: string;
infoTooltip?: string;
labelColor?: string;
labelCircleColor?: string;
labelFontWeight?: string;
Expand Down Expand Up @@ -256,6 +257,7 @@ export interface ICategoricalTrackSpec {
naLegendLabel?: string;
description?: string;
info?: string;
infoTooltip?: string;
}

export const GENETIC_TRACK_GROUP_INDEX = 1;
Expand Down
14 changes: 14 additions & 0 deletions src/shared/components/oncoprint/OncoprintUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ import {
isGenericAssayCategoricalProfile,
isGenericAssayHeatmapProfile,
} from 'shared/components/oncoprint/ResultsViewOncoprintUtils';
import { getProfileDescriptionCaveat } from 'shared/lib/GenericAssayUtils/GenericAssayCommonUtils';

// Warning glyph shown in a track's info slot when its profile carries a caveat.
export const PROFILE_CAVEAT_GLYPH = '⚠';
import { ExtendedClinicalAttribute } from 'pages/resultsView/ResultsViewPageStoreUtils';
import { CaseAggregatedData } from 'shared/model/CaseAggregatedData';
import { AnnotatedExtendedAlteration } from 'shared/model/AnnotatedExtendedAlteration';
Expand Down Expand Up @@ -1651,11 +1655,16 @@ export function makeGenericAssayProfileCategoricalTracksMobxPromise(
const entityLinkMap = oncoprint.genericAssayPromises
.genericAssayEntitiesGroupedByGenericAssayTypeLinkMap
.result![profile.genericAssayType];
const caveat = getProfileDescriptionCaveat(profile.description);

return {
key: `GENERICASSAYCATEGORICALTRACK_${molecularProfileId},${entityId}`,
label: query.entityName,
description: query.description,
info: caveat ? PROFILE_CAVEAT_GLYPH : undefined,
infoTooltip: caveat
? `<b>${PROFILE_CAVEAT_GLYPH} Caveat:</b> ${caveat}`
: undefined,
molecularProfileId: query.molecularProfileId,
molecularProfileName:
molecularProfileIdToMolecularProfile[molecularProfileId]
Expand Down Expand Up @@ -1760,11 +1769,16 @@ export function makeGenericAssayProfileHeatmapTracksMobxPromise(
const entityLinkMap = oncoprint.genericAssayPromises
.genericAssayEntitiesGroupedByGenericAssayTypeLinkMap
.result![profile.genericAssayType];
const caveat = getProfileDescriptionCaveat(profile.description);

return {
key: `GENERICASSAYHEATMAPTRACK_${molecularProfileId},${entityId}`,
label: query.entityName,
description: query.description,
info: caveat ? PROFILE_CAVEAT_GLYPH : undefined,
infoTooltip: caveat
? `<b>${PROFILE_CAVEAT_GLYPH} Caveat:</b> ${caveat}`
: undefined,
molecularProfileId: query.molecularProfileId,
molecularProfileName:
molecularProfileIdToMolecularProfile[molecularProfileId]
Expand Down
36 changes: 36 additions & 0 deletions src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
filterGenericAssayEntitiesByGenes,
makeGenericAssayPlotsTabOption,
filterGenericAssayOptionsByGenes,
getProfileDescriptionCaveat,
} from './GenericAssayCommonUtils';
import { getServerConfig } from 'config/config';
import ServerConfigDefaults from 'config/serverConfigDefaults';
Expand Down Expand Up @@ -471,4 +472,39 @@ describe('GenericAssayCommonUtils', () => {
);
});
});

describe('getProfileDescriptionCaveat()', () => {
it('returns undefined when description is undefined or empty', () => {
assert.isUndefined(getProfileDescriptionCaveat(undefined));
assert.isUndefined(getProfileDescriptionCaveat(''));
});

it('returns undefined when there is no caveat marker', () => {
assert.isUndefined(
getProfileDescriptionCaveat('Cell Type Relative Fractions.')
);
});

it('extracts the caveat text after the marker', () => {
assert.equal(
getProfileDescriptionCaveat(
'Cell Type Relative Fractions. Caveat: Fractions are derived from CD45 FACS-sorted scRNA-seq.'
),
'Fractions are derived from CD45 FACS-sorted scRNA-seq.'
);
});

it('is case-insensitive on the marker', () => {
assert.equal(
getProfileDescriptionCaveat('caveat: something to note'),
'something to note'
);
});

it('returns undefined when the marker has no following text', () => {
assert.isUndefined(
getProfileDescriptionCaveat('Some description. Caveat: ')
);
});
});
});
34 changes: 25 additions & 9 deletions src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,8 @@ export async function fetchGenericAssayMetaByMolecularProfileIdsGroupByMolecular
} = {};
for (const profile of genericAssayProfiles) {
const suffix = getSuffixOfMolecularProfile(profile);
genericAssayMetaGroupByMolecularProfileId[
profile.molecularProfileId
] = metaBySuffix[suffix] || [];
genericAssayMetaGroupByMolecularProfileId[profile.molecularProfileId] =
metaBySuffix[suffix] || [];
}

return genericAssayMetaGroupByMolecularProfileId;
Expand Down Expand Up @@ -228,12 +227,14 @@ export function fetchGenericAssayDataByStableIdsAndMolecularIds(
stableIds: string[],
molecularProfileIds: string[]
) {
return getClient().fetchGenericAssayDataInMultipleMolecularProfilesUsingPOST({
genericAssayDataMultipleStudyFilter: {
genericAssayStableIds: stableIds,
molecularProfileIds: molecularProfileIds,
} as GenericAssayDataMultipleStudyFilter,
});
return getClient().fetchGenericAssayDataInMultipleMolecularProfilesUsingPOST(
{
genericAssayDataMultipleStudyFilter: {
genericAssayStableIds: stableIds,
molecularProfileIds: molecularProfileIds,
} as GenericAssayDataMultipleStudyFilter,
}
);
}

export function makeGenericAssayOption(meta: GenericAssayMeta) {
Expand Down Expand Up @@ -356,6 +357,21 @@ export function getCategoryOrderByGenericAssayType(genericAssayType: string) {
: undefined;
}

// A profile description may carry a curated caveat about how its data should be
// interpreted, flagged with a "Caveat:" marker (e.g. data derived from a sorted
// cell population). Everything after the marker is the caveat text, surfaced as
// a per-track warning so viewers see it without reading the profile description.
export function getProfileDescriptionCaveat(
description: string | undefined
): string | undefined {
if (!description) {
return undefined;
}
const match = /caveat:\s*([\s\S]+)/i.exec(description);
const caveat = match && match[1].trim();
return caveat ? caveat : undefined;
}

export function constructGeneRegex(hugoGeneSymbol: string) {
// Match whole gene symbol text and case-insensitive, non-alphanumeric characters is allowed after gene symbol
// Sometimes, gene symbol might appear in description text
Expand Down
Loading