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

Mutational signature plot with cosmic reference signature #4771

Merged
merged 2 commits into from
Jan 31, 2024
Merged
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion src/pages/patientView/PatientViewPageTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ export function tabs(
<MSKTab
key={8}
id="mutationalSignatures"
linkText="Mutational Signature Data"
linkText="Mutational Signatures"
hide={
pageComponent.patientViewPageStore
.mutationalSignatureMolecularProfiles.isPending ||
Expand Down Expand Up @@ -642,6 +642,10 @@ export function tabs(
pageComponent.patientViewPageStore
.samplesWithCountDataAvailable
}
samplesNotProfiled={
pageComponent.patientViewPageStore
.samplesNotProfiledForMutationalSignatures
}
onSampleChange={pageComponent.onSampleIdChange}
/>
</MSKTab>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as ClinicalInformationMutationalSignatureTable from './ClinicalInformationMutationalSignatureTable';
import React from 'react';
import { assert } from 'chai';
import { prepareMutationalSignatureDataForTable } from './ClinicalInformationMutationalSignatureTable';
import { prepareMutationalSignatureDataForTable } from '../mutationalSignatures/MutationalSignatureBarChartUtils';
import { IMutationalSignature } from 'shared/model/MutationalSignature';

const sampleMutationalSignatureMeta = [
Expand Down Expand Up @@ -84,7 +84,7 @@ describe('ClinicalInformationMutationalSignatureTable', () => {
it('takes mutational signature sample data and formats it for mutational signature table to render', () => {
let result = prepareMutationalSignatureDataForTable(
sampleMutationalSignatureData,
samples
['firstSample', 'secondSample']
);
assert.deepEqual(result, [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@ import LazyMobXTable, {
} from 'shared/components/lazyMobXTable/LazyMobXTable';
import styles from './style/mutationalSignatureTable.module.scss';
import { SHOW_ALL_PAGE_SIZE } from '../../../shared/components/paginationControls/PaginationControls';
import { IMutationalSignature } from '../../../shared/model/MutationalSignature';
import { getMutationalSignaturePercentage } from '../../../shared/lib/FormatUtils';
import _ from 'lodash';
import { observer } from 'mobx-react';
import { action, computed, makeObservable, observable } from 'mobx';
import { MUTATIONAL_SIGNATURES_SIGNIFICANT_PVALUE_THRESHOLD } from 'shared/lib/GenericAssayUtils/MutationalSignaturesUtils';
import { DownloadControlOption } from 'cbioportal-frontend-commons';
import { getServerConfig } from 'config/config';
import Tooltip from 'rc-tooltip';

import { ILazyMobXTableApplicationDataStore } from 'shared/lib/ILazyMobXTableApplicationDataStore';
export interface IClinicalInformationMutationalSignatureTableProps {
data: IMutationalSignature[];
parentCallback: (childData: string, visibility: boolean) => void;
data: IMutationalSignatureRow[];
url: string;
signature: string;
description: string;
samples: string[];
onRowClick: (d: IMutationalSignatureRow) => void;
onRowMouseEnter?: (d: IMutationalSignatureRow) => void;
onRowMouseLeave?: (d: IMutationalSignatureRow) => void;
dataStore: ILazyMobXTableApplicationDataStore<IMutationalSignatureRow>;
}

class MutationalSignatureTable extends LazyMobXTable<IMutationalSignatureRow> {}

interface IMutationalSignatureRow {
export interface IMutationalSignatureRow {
name: string;
sampleValues: {
[sampleId: string]: {
Expand All @@ -36,55 +37,13 @@ interface IMutationalSignatureRow {
url: string;
}

export function prepareMutationalSignatureDataForTable(
mutationalSignatureData: IMutationalSignature[],
samples: { id: string }[]
): IMutationalSignatureRow[] {
const tableData: IMutationalSignatureRow[] = [];
//group data by mutational signature
//[{id: mutationalsignatureid, samples: [{}, {}]}]
let sampleInvertedDataByMutationalSignature: Array<any> = _(
mutationalSignatureData
)
.groupBy(
mutationalSignatureSample => mutationalSignatureSample.meta.name
)
.map((mutationalSignatureSampleData, name) => ({
name,
samples: mutationalSignatureSampleData,
url: mutationalSignatureSampleData[0].meta.url,
}))
.value();
for (const mutationalSignature of sampleInvertedDataByMutationalSignature) {
let mutationalSignatureRowForTable: IMutationalSignatureRow = {
name: '',
sampleValues: {},
url: '',
};
mutationalSignatureRowForTable.name = mutationalSignature.name;
mutationalSignatureRowForTable.url = mutationalSignature.url;
for (const sample of mutationalSignature.samples) {
mutationalSignatureRowForTable.sampleValues[sample.sampleId] = {
value: sample.value,
confidence: sample.confidence,
};
}
if (
Object.keys(mutationalSignatureRowForTable.sampleValues).length ===
samples.length
) {
tableData.push(mutationalSignatureRowForTable);
}
}
return tableData;
}
@observer
export default class ClinicalInformationMutationalSignatureTable extends React.Component<
IClinicalInformationMutationalSignatureTableProps,
{}
> {
@observable selectedSignature = '';

@observable
selectedSignature: string;
constructor(props: IClinicalInformationMutationalSignatureTableProps) {
super(props);
makeObservable(this);
Expand All @@ -96,40 +55,33 @@ export default class ClinicalInformationMutationalSignatureTable extends React.C
this.selectedSignature = e.currentTarget.innerHTML;
}
@computed get uniqueSamples() {
return _.map(_.uniqBy(this.props.data, 'sampleId'), uniqSample => ({
id: uniqSample.sampleId,
}));
}

@computed get tableData() {
return prepareMutationalSignatureDataForTable(
this.props.data,
this.uniqueSamples
return _.map(
this.props.data.map(x => Object.keys(x.sampleValues))[0],
uniqSample => ({
id: uniqSample,
})
);
}

@computed get tooltipInfo() {
return (
<div
style={{ maxWidth: 450 }}
data-test="SignificantMutationalSignaturesTooltip"
style={{ maxWidth: 400 }}
data-test="SignificantMutationalSignaturesTableTooltip"
>
<div>
<h4>
<b>Signature:</b>
<h5>
<b>Signature: </b>
{this.props.signature}
</h4>
<p>
</h5>
<p style={{ fontSize: '12px' }}>
<b>Description: </b>
{this.props.description}
</p>
<p>
{this.props.url != '' && (
<a href={this.props.url} target="_blank">
External link to signature (opens new tab)
</a>
)}
{this.props.url == '' &&
'No link to external website available'}
<p style={{ fontSize: '12px' }}>
<a href={this.props.url} target="_blank">
External link to signature (opens new tab)
</a>
</p>
</div>
</div>
Expand All @@ -141,17 +93,13 @@ export default class ClinicalInformationMutationalSignatureTable extends React.C
{
name: 'Mutational Signature',
render: (data: IMutationalSignatureRow) => (
<Tooltip overlay={this.tooltipInfo}>
{
<span
onMouseOver={() =>
this.props.parentCallback(data.name, false)
}
>
{data[this.firstCol]}
</span>
}
</Tooltip>
<span>
<a target="_blank">{data[this.firstCol]}</a>
{' '}
<Tooltip overlay={this.tooltipInfo}>
{<i className="fa fa-info-circle"></i>}
</Tooltip>
</span>
),
download: (data: IMutationalSignatureRow) =>
`${data[this.firstCol]}`,
Expand All @@ -174,20 +122,23 @@ export default class ClinicalInformationMutationalSignatureTable extends React.C
MUTATIONAL_SIGNATURES_SIGNIFICANT_PVALUE_THRESHOLD ? ( //if it's a significant signature, bold the contribution
// Based on significant pvalue the span is created with style.mutationalSignatureValue for bold (sign)
// or normal styling (not signficant)
<span className={styles.mutationalSignatureValue}>
<span
className={styles.mutationalSignatureValue}
style={{ float: 'right' }}
>
{getMutationalSignaturePercentage(
data.sampleValues[col.id].value
)}
</span>
) : (
<span>
<span style={{ float: 'right' }}>
{getMutationalSignaturePercentage(
data.sampleValues[col.id].value
)}
</span>
)
) : (
<span>
<span style={{ float: 'right' }}>
{getMutationalSignaturePercentage(
data.sampleValues[col.id].value
)}
Expand All @@ -209,25 +160,27 @@ export default class ClinicalInformationMutationalSignatureTable extends React.C
.indexOf(filterStringUpper) > -1,
sortBy: (data: IMutationalSignatureRow) =>
data.sampleValues[col.id].value,
align: 'right' as 'right',
})),
];
}

public render() {
return (
<MutationalSignatureTable
columns={this.columns}
data={this.tableData}
showPagination={false}
initialItemsPerPage={SHOW_ALL_PAGE_SIZE}
showColumnVisibility={false}
initialSortColumn={this.uniqueSamples[0].id}
initialSortDirection="desc"
showCopyDownload={
getServerConfig().skin_hide_download_controls ===
DownloadControlOption.SHOW_ALL
}
/>
<div style={{ paddingTop: '0' }}>
<MutationalSignatureTable
columns={this.columns}
data={this.props.data}
dataStore={this.props.dataStore}
showPagination={false}
initialItemsPerPage={SHOW_ALL_PAGE_SIZE}
showColumnVisibility={false}
initialSortColumn={this.uniqueSamples[0].id}
initialSortDirection="desc"
onRowClick={this.props.onRowClick}
onRowMouseEnter={this.props.onRowMouseEnter}
/>
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,15 @@ export class PatientViewPageStore {
.filter((value, index, self) => self.indexOf(value) === index);
}

@computed get samplesNotProfiledForMutationalSignatures(): string[] {
const allSamples = this.samplesWithUniqueKeys.result.map(
sample => sample.sampleId
);
return allSamples.filter(
element => !this.samplesWithCountDataAvailable.includes(element)
);
}

readonly samplesWithoutCancerTypeClinicalData = remoteData(
{
await: () => [this.samples, this.clinicalDataForSamples],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const sampleMutationalSignatureData: IMutationalCounts[] = [

describe('MutationalSignatureBarChart', () => {
it('Takes unsorted IMutationalCounts[] and transforms it to sorted IColorDataChart', () => {
let result = getColorsForSignatures(sampleMutationalSignatureData);
let result = getColorsForSignatures(sampleMutationalSignatureData, '%');
assert.deepEqual(result, [
{
uniqueSampleKey: 's09e3B34',
Expand All @@ -97,6 +97,7 @@ describe('MutationalSignatureBarChart', () => {
colorValue: 'red',
label: 'A[C>T]G',
subcategory: ' ',
sublabel: ' ',
group: 'C>T',
},
{
Expand All @@ -112,6 +113,7 @@ describe('MutationalSignatureBarChart', () => {
colorValue: 'red',
label: 'A[C>T]G',
subcategory: ' ',
sublabel: ' ',
group: 'C>T',
},

Expand All @@ -125,16 +127,18 @@ describe('MutationalSignatureBarChart', () => {
mutationalSignatureClass: 'T>A',
version: 'v2',
value: 20,
colorValue: 'grey',
colorValue: '#99A3A4',
subcategory: ' ',
sublabel: ' ',
label: 'A[T>A]G',
group: 'T>A',
},
]);
});
it('Takes unsorted IMutationalCounts[] and transforms it to unsorted IColorDataChart', () => {
let result = getColorsForSignatures(
sampleMutationalSignatureDataWithoutClass
sampleMutationalSignatureDataWithoutClass,
'%'
);
assert.deepEqual(result, [
{
Expand All @@ -149,6 +153,7 @@ describe('MutationalSignatureBarChart', () => {
colorValue: 'red',
label: 'A[C>T]G',
subcategory: ' ',
sublabel: ' ',
mutationalSignatureClass: '',
group: 'C>T',
},
Expand All @@ -164,6 +169,7 @@ describe('MutationalSignatureBarChart', () => {
colorValue: 'red',
label: 'A[C>T]G',
subcategory: ' ',
sublabel: ' ',
mutationalSignatureClass: '',
group: 'C>T',
},
Expand All @@ -180,6 +186,7 @@ describe('MutationalSignatureBarChart', () => {
colorValue: 'red',
label: 'A[C>T]G',
subcategory: ' ',
sublabel: ' ',
mutationalSignatureClass: '',
group: 'C>T',
},
Expand Down
Loading
Loading