Skip to content

Commit

Permalink
Replace Vector Catalog in Cell Line Selector (cherry-picked) (#171)
Browse files Browse the repository at this point in the history
This commit already exists on master. This just cherry-picks it onto the
external-24q4 branch.
  • Loading branch information
rcreasi authored Jan 16, 2025
1 parent 49c9489 commit 81b6997
Show file tree
Hide file tree
Showing 23 changed files with 188 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from "react";
import {
convertDimensionToSliceId,
DatasetMetadataSelector,
DimensionSelect,
PlotConfigSelect,
} from "@depmap/data-explorer-2";
import styles from "../styles/cell_line_selector.scss";

interface Props {
onChange: (
sliceId: string | null,
valueType: "continuous" | "categorical"
) => void;
}

function DataColumnSelect({ onChange }: Props) {
const [valueType, setValueType] = useState<
"continuous" | "categorical" | null
>(null);
const [value, setValue] = useState<string | null>(null);

return (
<div>
<PlotConfigSelect
show
enable
placeholder="Choose source…"
value={valueType}
onChange={(nextValueType) => {
setValueType(nextValueType as "continuous" | "categorical");
onChange(null, nextValueType as "continuous" | "categorical");
setValue(null);
}}
options={{
categorical: "Model Property",
continuous: "Matrix Data",
}}
/>
{valueType === "continuous" && (
<DimensionSelect
className={styles.DimensionSelect}
mode="entity-only"
index_type="depmap_model"
value={null}
onChange={(dimension) => {
const sliceId = convertDimensionToSliceId(dimension);
onChange(sliceId, valueType);
}}
/>
)}
{valueType === "categorical" && (
<DatasetMetadataSelector
show
enable
slice_type="depmap_model"
value={value}
onChange={(partialOrCompleteSliceId: string | null) => {
setValue(partialOrCompleteSliceId);

if (
partialOrCompleteSliceId &&
partialOrCompleteSliceId.split("/").length === 4
) {
onChange(partialOrCompleteSliceId, valueType);
} else {
onChange(null, valueType);
}
}}
/>
)}
</div>
);
}

export default DataColumnSelect;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable */
import * as React from "react";
import { Link, VectorCatalog } from "@depmap/interactive";
import { fetchMetadataColumn } from "@depmap/data-explorer-2";
import { Link } from "@depmap/interactive";
import { Button } from "react-bootstrap";
import { CellData } from "../models/cellLines";
import update from "immutability-helper";
Expand All @@ -18,6 +19,7 @@ import {
inferColumnType,
} from "@depmap/long-table";
import { ApiContext } from "@depmap/api";
import DataColumnSelect from "./DataColumnSelect";

export interface LongTableCellLineSelectorProps {
idCol: string;
Expand Down Expand Up @@ -203,46 +205,26 @@ export class LongTableCellLineSelector extends React.Component<
<div style={{ padding: "10px" }}>
<strong>Add a data column</strong>
<br />
<VectorCatalog
catalog="continuous_and_categorical"
onSelection={(id: string, labels: Array<Link>) => {
let colLabel = "";
for (let i = 1; i < labels.length; i++) {
colLabel = colLabel.concat(" ").concat(labels[i].label);
}

this.context
.getApi()
.getVector(id)
.then((response: VectorResponse) => {
let newVector: Vector;
let newColType: "continuous" | "categorical" | null = null;
try {
if (response.values) {
newVector = {
cellLines: response.cellLines,
values: response.values,
};
newColType = "continuous";
} else if (response.categoricalValues) {
newVector = {
cellLines: response.cellLines,
values: response.categoricalValues,
};
newColType = "categorical";
} else {
throw "ERROR! neither continuous nor categorical values were returned";
}
this.setState({
vector: newVector,
vectorId: id,
newColLabel: colLabel,
newColType,
});
} catch (err) {
console.log(err);
}
<DataColumnSelect
onChange={(sliceId, valueType) => {
if (!sliceId) {
this.setState({
vector: undefined,
vectorId: undefined,
});
} else {
fetchMetadataColumn(sliceId).then((metadataColumn) => {
this.setState({
vector: {
cellLines: Object.keys(metadataColumn.indexed_values),
values: Object.values(metadataColumn.indexed_values),
},
vectorId: sliceId,
newColLabel: metadataColumn.label,
newColType: valueType,
});
});
}
}}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ $link_blue_hover: #23527c;
$modal-height: 72vh;
$bottom-div-height: 35px;

.DimensionSelect {
margin-top: 12px;
}

// TODO: Get rid of :global and convert the corresponding component to CSS
// Module format.
:global {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ const CellLineSelectorModal = React.lazy(
)
);

const getVectorCatalogApi = () => {
throw new Error("Vector Catalog API is no longer supported!");
};

export default function renderCellLineSelectorModal(
getApi: ApiContextInterface["getApi"],
getVectorCatalogApi: ApiContextInterface["getVectorCatalogApi"],
container: HTMLElement | null
) {
if (!container) {
Expand All @@ -23,18 +26,12 @@ export default function renderCellLineSelectorModal(
}

const dapi = getApi();
const apiFunctions = {
depmap: {
getApi,
getVectorCatalogApi,
},
};

// Unmount a previous instance if any (otherwise this is a no-op).
ReactDOM.unmountComponentAtNode(container);

ReactDOM.render(
<ApiContext.Provider value={apiFunctions.depmap}>
<ApiContext.Provider value={{ getApi, getVectorCatalogApi }}>
<React.Suspense fallback={null}>
<CellLineSelectorModal
getCellLineSelectorLines={() => dapi.getCellLineSelectorLines()}
Expand All @@ -50,7 +47,6 @@ export default function renderCellLineSelectorModal(

export function renderCellLineSelectorModalUsingBBApi(
getApi: ApiContextInterface["getApi"],
getVectorCatalogApi: ApiContextInterface["getVectorCatalogApi"],
container: HTMLElement | null
) {
if (!container) {
Expand All @@ -61,17 +57,12 @@ export function renderCellLineSelectorModalUsingBBApi(
}

const bbapi = getApi();
const apiFunctions = {
breadbox: {
getApi,
getVectorCatalogApi,
},
};

// Unmount a previous instance if any (otherwise this is a no-op).
ReactDOM.unmountComponentAtNode(container);

ReactDOM.render(
<ApiContext.Provider value={apiFunctions.breadbox}>
<ApiContext.Provider value={{ getApi, getVectorCatalogApi }}>
<React.Suspense fallback={null}>
<CellLineSelectorModal
getCellLineSelectorLines={() => bbapi.getCellLineSelectorLines()}
Expand Down
3 changes: 3 additions & 0 deletions frontend/packages/@depmap/data-explorer-2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as DimensionSelect } from "./src/components/DimensionSelect";
export { default as SliceLabelSelect } from "./src/components/DimensionSelect/SliceLabelSelect";
export { default as ContextBuilderModal } from "./src/components/ContextBuilder/ContextBuilderModal";
export { default as ContextManager } from "./src/components/ContextManager";
export { default as DatasetMetadataSelector } from "./src/components/DatasetMetadataSelector";

export {
fetchContextLabels,
Expand All @@ -18,6 +19,7 @@ export {
fetchGeneTeaEnrichment,
fetchGeneTeaTermContext,
fetchLinearRegression,
fetchMetadataColumn,
fetchMetadataSlices,
fetchPlotDimensions,
fetchWaterfall,
Expand Down Expand Up @@ -52,6 +54,7 @@ export {

export {
capitalize,
convertDimensionToSliceId,
getDimensionTypeLabel,
isCompleteDimension,
isCompleteExpression,
Expand Down
6 changes: 5 additions & 1 deletion frontend/packages/@depmap/data-explorer-2/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,11 @@ export async function fetchContextSummary(

export async function fetchMetadataColumn(
slice_id: string
): Promise<{ slice_id: string; indexed_values: Record<string, string> }> {
): Promise<{
slice_id: string;
label: string;
indexed_values: Record<string, string>;
}> {
return postJson("/get_metadata", { metadata: { slice_id } });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function CellLineSelectorModal({
Set<string>
>(new Set());

const { getApi, getVectorCatalogApi } = useContext(ApiContext);
const { getApi } = useContext(ApiContext);

useEffect(() => {
getApi()
Expand All @@ -91,7 +91,7 @@ function CellLineSelectorModal({
setSelection(modelNamesToIDs(initialSelection, td));
}
});
}, [useModelNames, initialSelection, getApi, getVectorCatalogApi]);
}, [useModelNames, initialSelection, getApi]);

useEffect(() => {
getApi()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import React, { useEffect, useState } from "react";
import {
fetchMetadataSlices,
MetadataSlices,
PlotConfigSelect,
SliceLabelSelector,
} from "@depmap/data-explorer-2";
import { fetchMetadataSlices, MetadataSlices } from "../../api";
import PlotConfigSelect from "../PlotConfigSelect";
import SliceLabelSelector from "../SliceLabelSelector";
import {
containsPartialSlice,
getDatasetIdFromSlice,
getMetadataSliceTypeLabelFromSlice,
getOptions,
sliceLabel,
slicePrefix,
} from "src/data-explorer-2/components/ConfigurationPanel/DatasetMetadataSelector/utils";
import styles from "src/data-explorer-2/styles/ConfigurationPanel.scss";
} from "./utils";

interface Props {
show: boolean;
Expand Down Expand Up @@ -58,7 +54,7 @@ function DatasetMetadataSelector({
}

return (
<div className={styles.colorBySelector}>
<div>
<PlotConfigSelect
label={null}
isClearable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MetadataSlices } from "@depmap/data-explorer-2";
import { MetadataSlices } from "../../api";

export const slicePrefix = (slices: MetadataSlices, value: string) => {
let out = "";
Expand Down
32 changes: 32 additions & 0 deletions frontend/packages/@depmap/data-explorer-2/src/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export const isCompleteExpression = (expr: any) => {
return false;
}

if (typeof expr === "boolean") {
return true;
}

if (expr.and && expr.and.length === 0) {
return false;
}
Expand Down Expand Up @@ -91,6 +95,34 @@ export const isSampleType = (dimensionType: string | null | undefined) => {
);
};

export function convertDimensionToSliceId(
dimension: Partial<DataExplorerPlotConfigDimension>
) {
if (!isCompleteDimension(dimension)) {
return null;
}

if (dimension.axis_type !== "raw_slice") {
throw new Error("Cannot convert a context to a slice ID!");
}

if (isSampleType(dimension.slice_type)) {
throw new Error(
"Cannot convert a sample to a slice ID! Only features are supported."
);
}

const expr = dimension.context.expr as { "==": [object, string] };
const feature = expr["=="][1];

return [
"slice",
urlLibEncode(dimension.dataset_id),
urlLibEncode(feature),
"label",
].join("/");
}

export const capitalize = (str: string) => {
return str && str.replace(/\b[a-z]/g, (c: string) => c.toUpperCase());
};
Expand Down
6 changes: 3 additions & 3 deletions frontend/packages/elara-frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import "bootstrap/dist/css/bootstrap.css";
// Include this after bootstrap so we can override its styles.
import "./index.scss";
import { ApiContext } from "@depmap/api";
import { VectorCatalogApi } from "@depmap/interactive";

const DataExplorer = React.lazy(() => import("src/pages/DataExplorer"));
const Datasets = React.lazy(() => import("@depmap/dataset-manager"));
Expand Down Expand Up @@ -45,9 +44,10 @@ const App = () => {
})();
}, [bbapi]);

const vectorCatalogApi = new VectorCatalogApi(bbapi);
const getApi = () => bbapi;
const getVectorCatalogApi = () => vectorCatalogApi;
const getVectorCatalogApi = () => {
throw new Error("Vector Catalog API is no longer supported!");
};

return (
<ApiContext.Provider value={{ getApi, getVectorCatalogApi }}>
Expand Down
Loading

0 comments on commit 81b6997

Please sign in to comment.