')
.addClass(TOOLTIP_DIV_CLASS)
.append(getCaseViewElt(dataUnderMouse, !!link_id))
.append('
')
.append(ret);
};
}
export function makeHeatmapTrackTooltip(
trackSpec: Pick<
IBaseHeatmapTrackSpec,
'tooltipValueLabel' | 'molecularAlterationType'
>,
link_id?: boolean
) {
return function(dataUnderMouse: any[]) {
let data_header = '';
let valueTextElement = tooltipTextElementNaN;
let categoryTextElement = '';
if (trackSpec.tooltipValueLabel) {
data_header = `${trackSpec.tooltipValueLabel}: `;
} else {
switch (trackSpec.molecularAlterationType) {
case AlterationTypeConstants.MRNA_EXPRESSION:
data_header = 'MRNA: ';
break;
case AlterationTypeConstants.PROTEIN_LEVEL:
data_header = 'PROT: ';
break;
case AlterationTypeConstants.METHYLATION:
data_header = 'METHYLATION: ';
break;
case AlterationTypeConstants.GENERIC_ASSAY:
// track for GENERIC_ASSAY type always has the genericAssayType
data_header = `${deriveDisplayTextFromGenericAssayType(
(trackSpec as IHeatmapTrackSpec).genericAssayType!
)}: `;
break;
default:
data_header = 'Value: ';
break;
}
}
let profileDataSum = 0;
const profileCategories: string[] = [];
let profileDataCount = 0;
let categoryCount = 0;
for (const d of dataUnderMouse) {
if (
d.profile_data !== null &&
typeof d.profile_data !== 'undefined'
) {
if (
trackSpec.molecularAlterationType ===
AlterationTypeConstants.GENERIC_ASSAY &&
d.category
) {
profileCategories.push(d.category);
categoryCount += 1;
} else {
profileDataSum += d.profile_data;
profileDataCount += 1;
}
}
}
if (profileDataCount > 0) {
const profileDisplayValue = (
profileDataSum / profileDataCount
).toFixed(2);
if (profileDataCount === 1) {
valueTextElement = profileDisplayValue;
} else {
valueTextElement = `${profileDisplayValue} (average of ${profileDataCount} values)`;
}
}
if (categoryCount > 0) {
if (profileDataCount === 0 && categoryCount === 1) {
categoryTextElement = profileCategories[0];
} else if (profileDataCount > 0 && categoryCount === 1) {
categoryTextElement = `${profileCategories[0]}`;
} else {
categoryTextElement = `${_.uniq(profileCategories).join(
', '
)} (${categoryCount} data points)`;
}
}
let ret = data_header;
if (valueTextElement !== tooltipTextElementNaN || categoryCount === 0) {
ret += '
';
}
if (valueTextElement !== tooltipTextElementNaN && categoryCount > 0) {
ret += ' and ';
}
if (categoryCount > 0) {
ret += '
')
.addClass(TOOLTIP_DIV_CLASS)
.append(getCaseViewElt(dataUnderMouse, !!link_id))
.append('
')
.append(ret);
};
}
export function makeGeneticTrackTooltip_getCoverageInformation(
profiled_in:
| { genePanelId?: string; molecularProfileId: string }[]
| undefined,
not_profiled_in:
| { genePanelId?: string; molecularProfileId: string }[]
| undefined,
alterationTypesInQuery?: string[],
molecularProfileIdToMolecularProfile?: {
[molecularProfileId: string]: MolecularProfile;
}
): {
dispProfiledGenePanelIds: string[];
dispNotProfiledGenePanelIds: string[];
dispProfiledIn: string[] | undefined;
dispNotProfiledIn: string[] | undefined;
dispAllProfiled: boolean;
dispNotProfiled: boolean;
} {
let dispProfiledGenePanelIds: string[] = [];
let dispProfiledGenePanelIdsMap: { [genePanelId: string]: string } = {};
let dispProfiledIn: string[] | undefined = undefined;
let dispProfiledInMap: { [molecularProfileId: string]: string } = {};
let dispNotProfiledIn: string[] | undefined = undefined;
let dispNotProfiledGenePanelIds: string[] = [];
let profiledInTypes: { [type: string]: string } | undefined = undefined;
if (profiled_in) {
dispProfiledGenePanelIds = _.uniq(
(profiled_in.map(x => x.genePanelId) as (
| string
| undefined
)[]).filter(x => !!x) as string[]
);
dispProfiledIn = _.uniq(profiled_in.map(x => x.molecularProfileId));
if (molecularProfileIdToMolecularProfile) {
profiledInTypes = _.keyBy(
dispProfiledIn,
molecularProfileId =>
molecularProfileIdToMolecularProfile[molecularProfileId]
.molecularAlterationType
);
}
dispProfiledInMap = _.keyBy(dispProfiledIn);
dispProfiledGenePanelIdsMap = _.keyBy(dispProfiledGenePanelIds);
}
if (not_profiled_in) {
dispNotProfiledIn = _.uniq(
not_profiled_in.map(x => x.molecularProfileId)
).filter(x => !dispProfiledInMap[x]); // filter out profiles in profiled_in to avoid confusing tooltip (this occurs e.g. w multiple samples, one profiled one not)
if (
profiledInTypes &&
alterationTypesInQuery &&
molecularProfileIdToMolecularProfile
) {
let notProfiledInTypes = _.keyBy(
dispNotProfiledIn,
molecularProfileId =>
molecularProfileIdToMolecularProfile[molecularProfileId]
.molecularAlterationType
);
// add an entry to 'not profiled in' for each alteration type in the query iff the sample is not profiled in a profile of that type, and that type is not already accounted for.
// This is for the case of multiple study query - eg one study has CNA profile, the other doesnt, and we want to show in a tooltip from the other study that
// the sample is not profiled for CNA. If the study actually has a CNA profile, then we wont show "not profiled for copy number alterations" because
// that will be filtered out below because its in profiledInTypes or notProfiledInTypes. Otherwise, CNA will be in alterationTypesInQuery,
// and it wont be covered in profiledInTypes or notProfiledInTypes, so it will make sense to say "copy number alterations" in that generality.
dispNotProfiledIn = dispNotProfiledIn.concat(
alterationTypesInQuery
.filter(t => !profiledInTypes![t] && !notProfiledInTypes[t])
.map(
t =>
AlterationTypeText[
t as keyof typeof AlterationTypeText
]
)
);
}
dispNotProfiledGenePanelIds = _.uniq(
not_profiled_in.map(x => x.genePanelId)
).filter(x => !!x && !dispProfiledGenePanelIdsMap[x]) as string[];
}
const dispAllProfiled = !!(
dispProfiledIn &&
dispProfiledIn.length &&
dispNotProfiledIn &&
!dispNotProfiledIn.length
);
const dispNotProfiled = !!(
dispNotProfiledIn &&
dispNotProfiledIn.length &&
dispProfiledIn &&
!dispProfiledIn.length
);
return {
dispProfiledGenePanelIds,
dispNotProfiledGenePanelIds,
dispProfiledIn,
dispNotProfiledIn,
dispAllProfiled,
dispNotProfiled,
};
}
export function getCaseViewElt(
dataUnderMouse: {
sample?: string;
patient: string;
study_id: string;
}[],
caseViewLinkout: boolean
) {
if (!dataUnderMouse.length) {
return '';
}
let caseIdElt;
if (dataUnderMouse[0].sample) {
if (dataUnderMouse.length > 1) {
caseIdElt = caseViewLinkout
? `
({
studyId: d.study_id,
patientId: d.patient,
}))
)} target="_blank">View these ${
dataUnderMouse.length
} samples`
: `
${dataUnderMouse.length} samples`;
} else {
caseIdElt = caseViewLinkout
? sampleViewAnchorTag(
dataUnderMouse[0].study_id,
dataUnderMouse[0].sample
)
: `
${dataUnderMouse[0].sample}`;
}
} else if (dataUnderMouse[0].patient) {
if (dataUnderMouse.length > 1) {
caseIdElt = caseViewLinkout
? `
({
studyId: d.study_id,
patientId: d.patient!,
}))
)} target="_blank">View these ${
dataUnderMouse.length
} patients`
: `
${dataUnderMouse.length} patients`;
} else {
caseIdElt = caseViewLinkout
? patientViewAnchorTag(
dataUnderMouse[0].study_id,
dataUnderMouse[0].patient
)
: `
${dataUnderMouse[0].patient}`;
}
} else {
caseIdElt = '';
}
return caseIdElt;
}