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
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import {
CompoundDoseCurveData,
CurveParams,
CurvePlotPoints,
CompoundSummaryResponse,
DRCDatasetOptions,
} from "@depmap/types";
import { uri } from "../../uriTemplateTag";
import { getJson } from "../client";

export function getDoseResponsePoints(
datasetName: string,
depmapId: string,
compoundLabel: string
) {
return getJson<{
curve_params: Array<CurveParams>;
points: Array<CurvePlotPoints>;
}>(uri`/compound/dosecurve/${datasetName}/${depmapId}/${compoundLabel}`);
}

export function getDoseResponseTable(datasetName: string, xrefFull: string) {
return getJson<any>(uri`/compound/dosetable/${datasetName}/${xrefFull}`);
}

export function getCompoundDoseCurveData(
compoundId: string,
drcDatasetLabel: string,
Expand Down Expand Up @@ -53,3 +36,20 @@ export function getPrioritizedDataset(
params
);
}

export function getCompoundSummary(
compoundId: string,
compoundName: string,
compoundDatasetIds: string[] = []
): Promise<CompoundSummaryResponse> {
const params = {
compound_id: compoundId,
compound_label: compoundName,
compound_dataset_ids: compoundDatasetIds,
};

return getJson<CompoundSummaryResponse>(
`/api/compound/compound_summary`,
params
);
}
6 changes: 0 additions & 6 deletions frontend/packages/@depmap/globals/src/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,9 @@ function polyfillProxy() {
"saveNewContext",
"editContext",
"repairContent",
"initPredictiveTab",
"initDoseResponseTab",
"initWideTable",
"initEntitySummary",
"initSublineagePlot",
"initCelfiePage",
"initEnrichmentTile",
"initHeatmapTile",
"initStructureAndDetailTile",
].forEach((prop) => {
Object.defineProperty(proxy, prop, {
get() {
Expand Down
22 changes: 22 additions & 0 deletions frontend/packages/@depmap/types/src/compounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,25 @@ export interface DRCDatasetOptions {
drc_dataset_label: string;
log_auc_dataset_given_id?: string;
}

export type DatasetOption = {
dataset: string;
entity: number;
id: string;
label: string;
};

export interface SensitivityTabSummary {
initialSelectedDataset: DatasetOption;
size_biom_enum_name: string;
color: string;
figure: { name: number };
show_auc_message: boolean;
summary_options: DatasetOption[];
}

export interface CompoundSummaryResponse {
sensitivity_summary: SensitivityTabSummary | null;
heatmap_dose_curve_options: DRCDatasetOptions[];
correlation_analysis_options: DRCDatasetOptions[];
}
49 changes: 49 additions & 0 deletions frontend/packages/portal-frontend/src/apps/compoundPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import "src/public-path";
import React from "react";
import ReactDOM from "react-dom";
import ErrorBoundary from "src/common/components/ErrorBoundary";
import CompoundPage from "src/compound/components/CompoundPage";

const container = document.getElementById("react-compound-page-root");
const dataElement = document.getElementById("react-compound-page-data");
if (!dataElement || !dataElement.textContent) {
throw new Error(
`Expected a DOM element like <script type="application/json">{ ... }</script>'`
);
}

const data = JSON.parse(dataElement.textContent);

const {
isMobile,
order,
compoundName,
compoundId,
aka, // Comma separated string of compound aliases
compoundUnits,
predictabilityCustomDownloadsLink,
predictabilityMethodologyLink,
hasDatasets,
showPredictabilityTab,
} = data;

const App = () => {
return (
<ErrorBoundary>
<CompoundPage
isMobile={isMobile}
order={order}
compoundName={compoundName}
compoundId={compoundId}
aka={aka}
compoundUnits={compoundUnits}
predictabilityCustomDownloadsLink={predictabilityCustomDownloadsLink}
predictabilityMethodologyLink={predictabilityMethodologyLink}
hasDatasets={hasDatasets}
showPredictabilityTab={showPredictabilityTab}
/>
</ErrorBoundary>
);
};

ReactDOM.render(<App />, container);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, {
useCallback,
useMemo,
} from "react";
import { TopFeatureValue } from "@depmap/types";
import { DatasetOption, TopFeatureValue } from "@depmap/types";
import { NetworkOverrepresentation } from "src/celfie/components/NetworkOverrepresentation";
import {
ConstellationGraphInputs,
Expand All @@ -30,7 +30,6 @@ import { Option } from "src/common/models/utilities";
import { UnivariateAssociationsParams, ComputeResponse } from "@depmap/compute";
import { ProgressTracker } from "@depmap/common-components";
import * as Plotly from "plotly.js";
import { DatasetOption } from "src/entity/components/EntitySummary";
import { ColorByOption } from "src/celfie/models/celfie";
import HelpModal from "src/common/components/HelpModal";
import { getNumGenes } from "src/celfie/utilities/celfieUtils";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from "react";
import styles from "../styles/CompoundPage.scss";
import CompoundPageTabs from "./CompoundPageTabs";
import CompoundPageHeader from "./CompoundPageHeader";
import { useCompoundPageData } from "../hooks/useCompoundPageData";
import { enabledFeatures } from "@depmap/globals";

interface Props {
isMobile: boolean;
order: any;
compoundName: string;
compoundId: string;
aka: string; // Comma separated list of compound aliases
compoundUnits: string;
predictabilityCustomDownloadsLink: string;
predictabilityMethodologyLink: string;
hasDatasets: boolean;
showPredictabilityTab: boolean;
}

const CompoundPage = ({
isMobile,
order,
compoundName,
compoundId,
aka, // Comma separated string of compound aliases
compoundUnits,
predictabilityCustomDownloadsLink,
predictabilityMethodologyLink,
hasDatasets,
showPredictabilityTab,
}: Props) => {
const {
isLoading,
sensitivitySummary,
initialSelectedDataset,
doseCurveOptions,
heatmapOptions,
correlationAnalysisOptions,
showEnrichedLineages,
} = useCompoundPageData(compoundId, compoundName);

return (
<div className={styles.CompoundPage}>
<CompoundPageHeader compoundName={compoundName} aka={aka} />
{!isLoading && (
<CompoundPageTabs
isMobile={isMobile}
order={order}
compoundName={compoundName}
compoundId={compoundId}
compoundUnits={compoundUnits}
predictabilityCustomDownloadsLink={predictabilityCustomDownloadsLink}
predictabilityMethodologyLink={predictabilityMethodologyLink}
hasDatasets={hasDatasets}
showPredictabilityTab={showPredictabilityTab}
showDoseCurvesTab={
doseCurveOptions.length > 0 && enabledFeatures.new_dose_curves_tab
}
showHeatmapTab={
heatmapOptions.length > 0 && enabledFeatures.heatmap_tab
}
showCorrelationAnalysisTab={correlationAnalysisOptions.length > 0}
showEnrichedLineages={showEnrichedLineages}
showCorrelatedDependenciesTile={
enabledFeatures.compound_correlated_dependencies_tile
}
showRelatedCompoundTiles={enabledFeatures.related_compounds_tile}
doseCurveTabOptions={doseCurveOptions}
heatmapTabOptions={heatmapOptions}
correlationAnalysisOptions={correlationAnalysisOptions}
sensitivitySummary={sensitivitySummary}
initialSelectedDataset={initialSelectedDataset}
/>
)}
</div>
);
};

export default CompoundPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import styles from "../styles/CompoundPage.scss";

interface Props {
compoundName: string;
aka: string;
}

const CompoundPageHeader = ({ compoundName, aka }: Props): JSX.Element => {
return (
<div className={styles.header}>
<div className={styles.symbol}>{compoundName}</div>
<div className={styles.headerInfoContainer}>
<div className={styles.headerInfoContainer}>
{aka && (
<div className={styles.otherInfo}>
Also known as: <span className={styles.infoContent}>{aka}</span>
</div>
)}
</div>
</div>
</div>
);
};

export default CompoundPageHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from "react";
import AsyncTile from "src/common/components/AsyncTile";
import { CardContainer, CardColumn } from "src/common/components/Card";

interface Props {
compoundName: string;
showPredictability: boolean;
showHeatmap: boolean;
showEnrichedLineages: boolean;
showCorrelatedDependenciesTile: boolean;
showRelatedCompoundsTile: boolean;
orderedTiles: [CompoundTileTypeEnum, number][][];
hasDatasets: boolean;
isMobile: boolean;
}

export enum CompoundTileTypeEnum {
Selectivity = "selectivity",
Predictability = "predictability",
Description = "description",
Sensitivity = "sensitivity",
Availability = "availability",
Celfie = "celfie",
Heatmap = "heatmap",
Correlated_dependencies = "correlated_dependencies",
Related_compounds = "related_compounds",
Correlated_expression = "correlated_expression",
}
/* match to portal-backend tile enum */

const CompoundPageOverview = ({
compoundName,
showPredictability,
showHeatmap,
showEnrichedLineages,
showCorrelatedDependenciesTile,
showRelatedCompoundsTile,
orderedTiles,
hasDatasets,
isMobile,
}: Props) => {
// We have an array of arrays. Each child array represents the tiles of a single column. Each tile is a tuple,
// with the name of the tile (i.e. essentiality) at index 0

const shouldShowTile = (tile: [CompoundTileTypeEnum, number]) => {
switch (tile[0]) {
case CompoundTileTypeEnum.Heatmap:
return showHeatmap;
case CompoundTileTypeEnum.Selectivity:
return showEnrichedLineages;
case CompoundTileTypeEnum.Predictability:
return showPredictability;
case CompoundTileTypeEnum.Correlated_dependencies:
return showCorrelatedDependenciesTile;
case CompoundTileTypeEnum.Related_compounds:
return showRelatedCompoundsTile;

default:
return true;
}
};

const getTileIfOkayToShow = (
tile: [CompoundTileTypeEnum, number],
key: [CompoundTileTypeEnum, number]
) => {
let resultTile: JSX.Element | null = (
<AsyncTile
key={key[0]}
url={`/tile/compound/${tile[0]}/${compoundName}`}
/>
);

// Match tiles with tabs... On occasion we have to show a tab, but not the tile (i.e. Celfie tab but not tile for HNF1B)
if (!shouldShowTile(tile)) {
resultTile = null;
}

return resultTile;
};

return (
<>
{isMobile ? (
<CardContainer>
<CardColumn>
{orderedTiles.map((column) => (
<div key={column.toString()}>
{column.map((tile) =>
hasDatasets ? getTileIfOkayToShow(tile, tile) : <></>
)}
</div>
))}
</CardColumn>
</CardContainer>
) : (
<CardContainer>
{orderedTiles.map((column) => (
<CardColumn key={column.toString()}>
{column.map((tile) => getTileIfOkayToShow(tile, tile))}
</CardColumn>
))}
</CardContainer>
)}
</>
);
};

export default CompoundPageOverview;
Loading