From b7fd6efd1873e2dda6d77b3b3d07e83612938b7d Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 17 Oct 2023 06:02:36 -0400 Subject: [PATCH 01/15] successful correlation compute --- .../plugins/correlationAssayMetadata.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx index 67f1acee0a..213a7c2609 100644 --- a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx +++ b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx @@ -1,5 +1,5 @@ import { useCollectionVariables, useStudyMetadata } from '../../..'; -import { VariableDescriptor } from '../../../types/variable'; +import { VariableCollectionDescriptor } from '../../../types/variable'; import { ComputationConfigProps, ComputationPlugin } from '../Types'; import { isEqual, partial } from 'lodash'; import { useConfigChangeHandler, assertComputationWithConfig } from '../Utils'; @@ -33,7 +33,7 @@ export type CorrelationAssayMetadataConfig = t.TypeOf< // eslint-disable-next-line @typescript-eslint/no-redeclare export const CorrelationAssayMetadataConfig = t.type({ - collectionVariable: VariableDescriptor, + collectionVariable1: VariableCollectionDescriptor, correlationMethod: t.string, }); @@ -63,8 +63,8 @@ function CorrelationAssayMetadataConfigDescriptionComponent({ const { configuration } = computation.descriptor; const collectionVariable = - 'collectionVariable' in configuration - ? configuration.collectionVariable + 'collectionVariable1' in configuration + ? configuration.collectionVariable1 : undefined; const correlationMethod = 'correlationMethod' in configuration @@ -145,7 +145,7 @@ export function CorrelationAssayMetadataConfiguration( const collectionVarItems = useMemo(() => { return collections.map((collectionVar) => ({ value: { - variableId: collectionVar.id, + collectionId: collectionVar.id, entityId: collectionVar.entityId, }, display: @@ -154,11 +154,11 @@ export function CorrelationAssayMetadataConfiguration( }, [collections]); const selectedCollectionVar = useMemo(() => { - if (configuration && 'collectionVariable' in configuration) { + if (configuration && 'collectionVariable1' in configuration) { const selectedItem = collectionVarItems.find((item) => isEqual(item.value, { - variableId: configuration.collectionVariable.variableId, - entityId: configuration.collectionVariable.entityId, + collectionId: configuration.collectionVariable1.collectionId, + entityId: configuration.collectionVariable1.entityId, }) ); return selectedItem; @@ -189,7 +189,7 @@ export function CorrelationAssayMetadataConfiguration( : 'Select the data' } items={collectionVarItems} - onSelect={partial(changeConfigHandler, 'collectionVariable')} + onSelect={partial(changeConfigHandler, 'collectionVariable1')} /> From 3319fb976b3e20cf66f14149b0e96af8e5dcc950 Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 17 Oct 2023 14:14:19 -0400 Subject: [PATCH 02/15] working bipartiteNetwork response --- .../components/src/plots/BipartiteNetwork.tsx | 11 +- .../eda/src/lib/core/api/DataClient/types.ts | 4 +- .../BipartiteNetworkVisualization.tsx | 155 +++++++++++------- 3 files changed, 103 insertions(+), 67 deletions(-) diff --git a/packages/libs/components/src/plots/BipartiteNetwork.tsx b/packages/libs/components/src/plots/BipartiteNetwork.tsx index fba1b4d747..f86844597e 100755 --- a/packages/libs/components/src/plots/BipartiteNetwork.tsx +++ b/packages/libs/components/src/plots/BipartiteNetwork.tsx @@ -17,7 +17,7 @@ import domToImage from 'dom-to-image'; export interface BipartiteNetworkProps { /** Bipartite network data */ - data: BipartiteNetworkData; + data: BipartiteNetworkData | undefined; /** Name of column 1 */ column1Name?: string; /** Name of column 2 */ @@ -32,6 +32,13 @@ export interface BipartiteNetworkProps { width?: number; } +const EmptyBipartiteNetworkData: BipartiteNetworkData = { + column1NodeIDs: [], + column2NodeIDs: [], + nodes: [], + links: [], +}; + // The BipartiteNetwork function draws a two-column network using visx. This component handles // the positioning of each column, and consequently the positioning of nodes and links. function BipartiteNetwork( @@ -39,7 +46,7 @@ function BipartiteNetwork( ref: Ref ) { const { - data, + data = EmptyBipartiteNetworkData, column1Name, column2Name, containerStyles = { width: '100%', height: DEFAULT_CONTAINER_HEIGHT }, diff --git a/packages/libs/eda/src/lib/core/api/DataClient/types.ts b/packages/libs/eda/src/lib/core/api/DataClient/types.ts index f11ccf8a8c..c4d357bc65 100755 --- a/packages/libs/eda/src/lib/core/api/DataClient/types.ts +++ b/packages/libs/eda/src/lib/core/api/DataClient/types.ts @@ -392,8 +392,8 @@ export const BipartiteNetworkResponse = type({ type({ source: NodeData, target: NodeData, - strokeWidth: number, - color: string, + linkColor: string, + linkWeight: string, }) ), }); diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 789133c0f7..b354765684 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -11,16 +11,27 @@ import BipartiteNetwork, { BipartiteNetworkProps, } from '@veupathdb/components/lib/plots/BipartiteNetwork'; import VolcanoSVG from './selectorIcons/VolcanoSVG'; // TEMP -import { BipartiteNetworkRequestParams } from '../../../api/DataClient/types'; +import { + BipartiteNetworkRequestParams, + BipartiteNetworkResponse, +} from '../../../api/DataClient/types'; import { BipartiteNetworkData, LinkData, NodeData, } from '@veupathdb/components/lib/types/plots/network'; import { twoColorPalette } from '@veupathdb/components/lib/types/plots/addOns'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { scaleOrdinal } from 'd3-scale'; import { uniq } from 'lodash'; +import { usePromise } from '../../../hooks/promise'; +import { + useDataClient, + useStudyEntities, + useStudyMetadata, +} from '../../../hooks/workspace'; +import DataClient from '../../../api/DataClient'; +import { CorrelationAssayMetadataConfig } from '../../computations/plugins/correlationAssayMetadata'; // end imports // Defaults @@ -64,32 +75,94 @@ interface Options // The bipartite network takes no input variables, because the received data will complete the plot. // Eventually the user will be able to control the significance and correlation coefficient values. function BipartiteNetworkViz(props: VisualizationProps) { - const { options, updateThumbnail } = props; + const { + options, + computation, + visualization, + updateThumbnail, + computeJobStatus, + filteredCounts, + filters, + } = props; + + const studyMetadata = useStudyMetadata(); + const { id: studyId } = studyMetadata; + const entities = useStudyEntities(filters); + const dataClient: DataClient = useDataClient(); + const computationConfiguration: CorrelationAssayMetadataConfig = computation + .descriptor.configuration as CorrelationAssayMetadataConfig; // Fake data - const data: BipartiteNetworkData = useMemo( - () => genBipartiteNetwork(100, 10), - [] + const data = usePromise( + useCallback(async (): Promise => { + // Only need to check compute job status and filter status, since there are no + // viz input variables. + console.log(filteredCounts); + if (computeJobStatus !== 'complete') return undefined; + if (filteredCounts.pending || filteredCounts.value == null) + return undefined; + + // There are _no_ viz request params for the volcano plot (config: {}). + // The data service streams the volcano data directly from the compute service. + const params = { + studyId, + filters, + config: {}, + computeConfig: computationConfiguration, + }; + console.log(params); + + const response = await dataClient.getVisualizationData( + computation.descriptor.type, + visualization.descriptor.type, + params, + BipartiteNetworkResponse + ); + console.log('new response'); + console.log(response); + + return response; + }, [ + computeJobStatus, + filteredCounts.pending, + filteredCounts.value, + filters, + studyId, + computationConfiguration, + computation.descriptor.type, + dataClient, + visualization.descriptor.type, + ]) ); + console.log(data); + // Assign color to links. // Color palettes live here in the frontend, but the backend knows that the edges should be two colors. // So we'll make it generalizable by mapping the values of the links.color prop to the palette. const uniqueLinkColors = uniq( - data.links.map((link) => link.color ?? DEFAULT_LINK_COLOR_DATA) + data.value?.links.map( + (link) => link.linkColor.toString() ?? DEFAULT_LINK_COLOR_DATA + ) ); const linkColorScale = scaleOrdinal() .domain(uniqueLinkColors) .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts. - const cleanedData: BipartiteNetworkData = { - ...data, - links: data.links.map((link) => { - return { - ...link, - color: linkColorScale(link.color ?? DEFAULT_LINK_COLOR_DATA), - }; - }), - }; + + const cleanedData = useMemo(() => { + if (!data.value) return undefined; + return { + ...data.value, + links: data.value.links.map((link) => { + return { + ...link, + color: linkColorScale( + link.linkColor.toString() ?? DEFAULT_LINK_COLOR_DATA + ), + }; + }), + }; + }, [data]); const plotRef = useUpdateThumbnailEffect( updateThumbnail, @@ -97,8 +170,10 @@ function BipartiteNetworkViz(props: VisualizationProps) { [cleanedData] ); + console.log(cleanedData); + const bipartiteNetworkProps: BipartiteNetworkProps = { - data: cleanedData, + data: cleanedData ?? undefined, }; const plotNode = ( @@ -125,49 +200,3 @@ function BipartiteNetworkViz(props: VisualizationProps) { ); } - -// TEMP: Gerenate a bipartite network with a given number of nodes and random edges -function genBipartiteNetwork( - column1nNodes: number, - column2nNodes: number -): BipartiteNetworkData { - // Create the first column of nodes - const column1Nodes: NodeData[] = [...Array(column1nNodes).keys()].map((i) => { - return { - id: String(i), - label: 'Node ' + String(i), - }; - }); - - // Create the second column of nodes - const column2Nodes: NodeData[] = [...Array(column2nNodes).keys()].map((i) => { - return { - id: String(i + column1nNodes), - label: 'Node ' + String(i + column1nNodes), - }; - }); - - // Create links - // Not worried about exactly how many edges we're adding just yet since this is - // used for stories only. Adding color here to mimic what the visualization - // will do. - const links: LinkData[] = [...Array(column1nNodes * 2).keys()].map(() => { - return { - source: column1Nodes[Math.floor(Math.random() * column1nNodes)], - target: column2Nodes[Math.floor(Math.random() * column2nNodes)], - strokeWidth: Math.random() * 2, - color: Math.random() > 0.5 ? '0' : '1', - }; - }); - - const nodes = column1Nodes.concat(column2Nodes); - const column1NodeIDs = column1Nodes.map((node) => node.id); - const column2NodeIDs = column2Nodes.map((node) => node.id); - - return { - nodes, - links, - column1NodeIDs, - column2NodeIDs, - }; -} From e87fc54b55ffa63443925b310cc66363aa1b1c03 Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 17 Oct 2023 14:25:09 -0400 Subject: [PATCH 03/15] add node display labels --- .../BipartiteNetworkVisualization.tsx | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index b354765684..d490e18fd6 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -30,6 +30,7 @@ import { useStudyEntities, useStudyMetadata, } from '../../../hooks/workspace'; +import { fixVarIdLabel } from '../../../utils/visualization'; import DataClient from '../../../api/DataClient'; import { CorrelationAssayMetadataConfig } from '../../computations/plugins/correlationAssayMetadata'; // end imports @@ -135,8 +136,6 @@ function BipartiteNetworkViz(props: VisualizationProps) { ]) ); - console.log(data); - // Assign color to links. // Color palettes live here in the frontend, but the backend knows that the edges should be two colors. // So we'll make it generalizable by mapping the values of the links.color prop to the palette. @@ -151,18 +150,36 @@ function BipartiteNetworkViz(props: VisualizationProps) { const cleanedData = useMemo(() => { if (!data.value) return undefined; + + // Find display labels + const nodesWithLabels = data.value.nodes.map((node) => { + // node.id is the entityId.variableId + const displayLabel = fixVarIdLabel( + node.id.split('.')[1], + node.id.split('.')[0], + entities + ); + + return { + id: node.id, + label: displayLabel, + }; + }); return { ...data.value, + nodes: nodesWithLabels, links: data.value.links.map((link) => { return { - ...link, + source: link.source, + target: link.target, + strokeWidth: Number(link.linkWeight), color: linkColorScale( link.linkColor.toString() ?? DEFAULT_LINK_COLOR_DATA ), }; }), }; - }, [data]); + }, [data, entities, linkColorScale]); const plotRef = useUpdateThumbnailEffect( updateThumbnail, @@ -170,8 +187,6 @@ function BipartiteNetworkViz(props: VisualizationProps) { [cleanedData] ); - console.log(cleanedData); - const bipartiteNetworkProps: BipartiteNetworkProps = { data: cleanedData ?? undefined, }; From d3b95dfbc1ce57f330ee8616101a7dbe612b5ef7 Mon Sep 17 00:00:00 2001 From: asizemore Date: Fri, 10 Nov 2023 10:42:16 -0500 Subject: [PATCH 04/15] update api to match new ds api --- .../eda/src/lib/core/api/DataClient/types.ts | 16 ++++++++++------ .../plugins/correlationAssayMetadata.tsx | 14 +++++++------- .../BipartiteNetworkVisualization.tsx | 7 ++++--- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/libs/eda/src/lib/core/api/DataClient/types.ts b/packages/libs/eda/src/lib/core/api/DataClient/types.ts index ad8f0ba9ec..38bcc05b98 100755 --- a/packages/libs/eda/src/lib/core/api/DataClient/types.ts +++ b/packages/libs/eda/src/lib/core/api/DataClient/types.ts @@ -395,12 +395,16 @@ export const BipartiteNetworkResponse = type({ column2NodeIDs: array(string), nodes: array(NodeData), links: array( - type({ - source: NodeData, - target: NodeData, - linkColor: string, - linkWeight: string, - }) + intersection([ + type({ + source: NodeData, + target: NodeData, + strokeWidth: string, + }), + partial({ + linkColor: string, + }), + ]) ), }); diff --git a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx index 213a7c2609..af1ecf06db 100644 --- a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx +++ b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx @@ -33,7 +33,7 @@ export type CorrelationAssayMetadataConfig = t.TypeOf< // eslint-disable-next-line @typescript-eslint/no-redeclare export const CorrelationAssayMetadataConfig = t.type({ - collectionVariable1: VariableCollectionDescriptor, + collectionVariable: VariableCollectionDescriptor, correlationMethod: t.string, }); @@ -63,8 +63,8 @@ function CorrelationAssayMetadataConfigDescriptionComponent({ const { configuration } = computation.descriptor; const collectionVariable = - 'collectionVariable1' in configuration - ? configuration.collectionVariable1 + 'collectionVariable' in configuration + ? configuration.collectionVariable : undefined; const correlationMethod = 'correlationMethod' in configuration @@ -154,11 +154,11 @@ export function CorrelationAssayMetadataConfiguration( }, [collections]); const selectedCollectionVar = useMemo(() => { - if (configuration && 'collectionVariable1' in configuration) { + if (configuration && 'collectionVariable' in configuration) { const selectedItem = collectionVarItems.find((item) => isEqual(item.value, { - collectionId: configuration.collectionVariable1.collectionId, - entityId: configuration.collectionVariable1.entityId, + collectionId: configuration.collectionVariable.collectionId, + entityId: configuration.collectionVariable.entityId, }) ); return selectedItem; @@ -189,7 +189,7 @@ export function CorrelationAssayMetadataConfiguration( : 'Select the data' } items={collectionVarItems} - onSelect={partial(changeConfigHandler, 'collectionVariable1')} + onSelect={partial(changeConfigHandler, 'collectionVariable')} /> diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index d490e18fd6..6ddbe7da16 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -135,13 +135,14 @@ function BipartiteNetworkViz(props: VisualizationProps) { visualization.descriptor.type, ]) ); + console.log(data); // Assign color to links. // Color palettes live here in the frontend, but the backend knows that the edges should be two colors. // So we'll make it generalizable by mapping the values of the links.color prop to the palette. const uniqueLinkColors = uniq( data.value?.links.map( - (link) => link.linkColor.toString() ?? DEFAULT_LINK_COLOR_DATA + (link) => link.linkColor?.toString() ?? DEFAULT_LINK_COLOR_DATA ) ); const linkColorScale = scaleOrdinal() @@ -172,9 +173,9 @@ function BipartiteNetworkViz(props: VisualizationProps) { return { source: link.source, target: link.target, - strokeWidth: Number(link.linkWeight), + strokeWidth: Number(link.strokeWidth), color: linkColorScale( - link.linkColor.toString() ?? DEFAULT_LINK_COLOR_DATA + link.linkColor?.toString() ?? DEFAULT_LINK_COLOR_DATA ), }; }), From d5c0480684952a7a051bd83ec10032489743e607 Mon Sep 17 00:00:00 2001 From: asizemore Date: Mon, 13 Nov 2023 06:53:08 -0500 Subject: [PATCH 05/15] update to new api --- packages/libs/eda/src/lib/core/api/DataClient/types.ts | 2 +- .../implementations/BipartiteNetworkVisualization.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/libs/eda/src/lib/core/api/DataClient/types.ts b/packages/libs/eda/src/lib/core/api/DataClient/types.ts index 38bcc05b98..6fccab2e84 100755 --- a/packages/libs/eda/src/lib/core/api/DataClient/types.ts +++ b/packages/libs/eda/src/lib/core/api/DataClient/types.ts @@ -402,7 +402,7 @@ export const BipartiteNetworkResponse = type({ strokeWidth: string, }), partial({ - linkColor: string, + color: string, }), ]) ), diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 6ddbe7da16..2e36af231f 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -142,7 +142,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { // So we'll make it generalizable by mapping the values of the links.color prop to the palette. const uniqueLinkColors = uniq( data.value?.links.map( - (link) => link.linkColor?.toString() ?? DEFAULT_LINK_COLOR_DATA + (link) => link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA ) ); const linkColorScale = scaleOrdinal() @@ -175,7 +175,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { target: link.target, strokeWidth: Number(link.strokeWidth), color: linkColorScale( - link.linkColor?.toString() ?? DEFAULT_LINK_COLOR_DATA + link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA ), }; }), From f1975fa1a48e8de4af8d209e3749fc6183530c3a Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 14 Nov 2023 13:37:49 -0500 Subject: [PATCH 06/15] one more api update --- .../eda/src/lib/core/api/DataClient/types.ts | 14 +++- .../BipartiteNetworkVisualization.tsx | 83 ++++++++++--------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/packages/libs/eda/src/lib/core/api/DataClient/types.ts b/packages/libs/eda/src/lib/core/api/DataClient/types.ts index 6fccab2e84..d927b70ff5 100755 --- a/packages/libs/eda/src/lib/core/api/DataClient/types.ts +++ b/packages/libs/eda/src/lib/core/api/DataClient/types.ts @@ -390,7 +390,7 @@ const NodeData = type({ id: string, }); -export const BipartiteNetworkResponse = type({ +export const BipartiteNetworkData = type({ column1NodeIDs: array(string), column2NodeIDs: array(string), nodes: array(NodeData), @@ -408,6 +408,18 @@ export const BipartiteNetworkResponse = type({ ), }); +const BipartiteNetworkConfig = type({ + column1Metadata: string, + column2Metadata: string, +}); + +export const BipartiteNetworkResponse = type({ + bipartitenetwork: type({ + data: BipartiteNetworkData, + config: BipartiteNetworkConfig, + }), +}); + export interface BipartiteNetworkRequestParams { studyId: string; filters: Filter[]; diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 2e36af231f..2735cbcc47 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -15,11 +15,6 @@ import { BipartiteNetworkRequestParams, BipartiteNetworkResponse, } from '../../../api/DataClient/types'; -import { - BipartiteNetworkData, - LinkData, - NodeData, -} from '@veupathdb/components/lib/types/plots/network'; import { twoColorPalette } from '@veupathdb/components/lib/types/plots/addOns'; import { useCallback, useMemo } from 'react'; import { scaleOrdinal } from 'd3-scale'; @@ -36,8 +31,8 @@ import { CorrelationAssayMetadataConfig } from '../../computations/plugins/corre // end imports // Defaults -const DEFAULT_CORRELATION_COEF_THRESHOLD = 0.9; -const DEFAULT_SIGNIFICANCE_THRESHOLD = 0.05; +const DEFAULT_CORRELATION_COEF_THRESHOLD = 0.05; // Ability for user to change this value not yet implemented. +const DEFAULT_SIGNIFICANCE_THRESHOLD = 0.05; // Ability for user to change this value not yet implemented. const DEFAULT_LINK_COLOR_DATA = '0'; const plotContainerStyles = { @@ -49,7 +44,7 @@ const plotContainerStyles = { }; export const bipartiteNetworkVisualization = createVisualizationPlugin({ - selectorIcon: VolcanoSVG, // TEMP + selectorIcon: VolcanoSVG, // TEMPORARY fullscreenComponent: BipartiteNetworkViz, createDefaultConfig: createDefaultConfig, }); @@ -74,7 +69,7 @@ interface Options // Bipartite Network Visualization // The bipartite network takes no input variables, because the received data will complete the plot. -// Eventually the user will be able to control the significance and correlation coefficient values. +// Eventually the user will be able to control the significance and correlation coefficient threshold values. function BipartiteNetworkViz(props: VisualizationProps) { const { options, @@ -93,25 +88,24 @@ function BipartiteNetworkViz(props: VisualizationProps) { const computationConfiguration: CorrelationAssayMetadataConfig = computation .descriptor.configuration as CorrelationAssayMetadataConfig; - // Fake data + // Get data from the compute job const data = usePromise( useCallback(async (): Promise => { // Only need to check compute job status and filter status, since there are no // viz input variables. - console.log(filteredCounts); if (computeJobStatus !== 'complete') return undefined; if (filteredCounts.pending || filteredCounts.value == null) return undefined; - // There are _no_ viz request params for the volcano plot (config: {}). - // The data service streams the volcano data directly from the compute service. const params = { studyId, filters, - config: {}, + config: { + correlationCoefThreshold: DEFAULT_CORRELATION_COEF_THRESHOLD, + significanceThreshold: DEFAULT_SIGNIFICANCE_THRESHOLD, + }, computeConfig: computationConfiguration, }; - console.log(params); const response = await dataClient.getVisualizationData( computation.descriptor.type, @@ -119,8 +113,6 @@ function BipartiteNetworkViz(props: VisualizationProps) { params, BipartiteNetworkResponse ); - console.log('new response'); - console.log(response); return response; }, [ @@ -135,41 +127,56 @@ function BipartiteNetworkViz(props: VisualizationProps) { visualization.descriptor.type, ]) ); - console.log(data); // Assign color to links. - // Color palettes live here in the frontend, but the backend knows that the edges should be two colors. - // So we'll make it generalizable by mapping the values of the links.color prop to the palette. + // Color palettes live here in the frontend, but the backend decides how to color links (ex. by sign of correlation, or avg degree of parent nodes). + // So we'll make assigning colors generalizable by mapping the values of the links.color prop to the palette. const uniqueLinkColors = uniq( - data.value?.links.map( + data.value?.bipartitenetwork.data.links.map( (link) => link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA ) ); + if (uniqueLinkColors.length > twoColorPalette.length) { + throw new Error( + `Found ${uniqueLinkColors.length} link colors but expected only two.` + ); + } + // The link colors should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain + // this way prevents a situation where if all links have color '1', we don't want them mapped to the + // color that is usually reserved for '-1'. + const linkColorScaleDomain = uniqueLinkColors.every((val) => + ['-1', '1'].includes(val) + ) + ? ['-1', '1'] + : uniqueLinkColors; const linkColorScale = scaleOrdinal() - .domain(uniqueLinkColors) - .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts. - + .domain(linkColorScaleDomain) + .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts (ex. not a correlation app). + // ANN YOU ARE HERE just going through and doing a mid PR clean. Also prolly going to try some stacked PRs for the + // rest of the todos const cleanedData = useMemo(() => { if (!data.value) return undefined; // Find display labels - const nodesWithLabels = data.value.nodes.map((node) => { - // node.id is the entityId.variableId - const displayLabel = fixVarIdLabel( - node.id.split('.')[1], - node.id.split('.')[0], - entities - ); + const nodesWithLabels = data.value.bipartitenetwork.data.nodes.map( + (node) => { + // node.id is the entityId.variableId + const displayLabel = fixVarIdLabel( + node.id.split('.')[1], + node.id.split('.')[0], + entities + ); - return { - id: node.id, - label: displayLabel, - }; - }); + return { + id: node.id, + label: displayLabel, + }; + } + ); return { - ...data.value, + ...data.value.bipartitenetwork.data, nodes: nodesWithLabels, - links: data.value.links.map((link) => { + links: data.value.bipartitenetwork.data.links.map((link) => { return { source: link.source, target: link.target, From 28798c93330e455ce2cd501c10c6b2078b48ad26 Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 14 Nov 2023 14:00:31 -0500 Subject: [PATCH 07/15] add plot subtitle to bp net --- .../plugins/correlationAssayMetadata.tsx | 8 +++++++- .../BipartiteNetworkVisualization.tsx | 18 ++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx index af1ecf06db..7db5ded77d 100644 --- a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx +++ b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx @@ -44,7 +44,13 @@ export const plugin: ComputationPlugin = { createDefaultConfiguration: () => undefined, isConfigurationValid: CorrelationAssayMetadataConfig.is, visualizationPlugins: { - bipartitenetwork: bipartiteNetworkVisualization, // Must match name in data service and in visualization.tsx + bipartitenetwork: bipartiteNetworkVisualization.withOptions({ + getPlotSubtitle(config) { + if (CorrelationAssayMetadataConfig.is(config)) { + return 'Showing links with an absolute correlation coefficient above '; // visualization will add in the actual value + } + }, + }), // Must match name in data service and in visualization.tsx }, }; diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 2735cbcc47..f6febe663e 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -3,7 +3,7 @@ import { useUpdateThumbnailEffect } from '../../../hooks/thumbnails'; import { PlotLayout } from '../../layouts/PlotLayout'; import { VisualizationProps } from '../VisualizationTypes'; import { createVisualizationPlugin } from '../VisualizationPlugin'; -import { LayoutOptions } from '../../layouts/types'; +import { LayoutOptions, TitleOptions } from '../../layouts/types'; import { RequestOptions } from '../options/types'; // Bipartite network imports @@ -28,6 +28,7 @@ import { import { fixVarIdLabel } from '../../../utils/visualization'; import DataClient from '../../../api/DataClient'; import { CorrelationAssayMetadataConfig } from '../../computations/plugins/correlationAssayMetadata'; +import { OutputEntityTitle } from '../OutputEntityTitle'; // end imports // Defaults @@ -65,6 +66,7 @@ export const BipartiteNetworkConfig = t.partial({ interface Options extends LayoutOptions, + TitleOptions, RequestOptions {} // Bipartite Network Visualization @@ -152,8 +154,8 @@ function BipartiteNetworkViz(props: VisualizationProps) { const linkColorScale = scaleOrdinal() .domain(linkColorScaleDomain) .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts (ex. not a correlation app). - // ANN YOU ARE HERE just going through and doing a mid PR clean. Also prolly going to try some stacked PRs for the - // rest of the todos + + // Clean and finalize data format. Specifically, assign link colors, add display labels const cleanedData = useMemo(() => { if (!data.value) return undefined; @@ -181,14 +183,17 @@ function BipartiteNetworkViz(props: VisualizationProps) { source: link.source, target: link.target, strokeWidth: Number(link.strokeWidth), - color: linkColorScale( - link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA - ), + color: link.color ? linkColorScale(link.color.toString()) : '#000000', }; }), }; }, [data, entities, linkColorScale]); + // plot subtitle + const plotSubtitle = + options?.getPlotSubtitle?.(computation.descriptor.configuration) + + DEFAULT_CORRELATION_COEF_THRESHOLD.toString(); + const plotRef = useUpdateThumbnailEffect( updateThumbnail, plotContainerStyles, @@ -212,6 +217,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { return (
+ Date: Tue, 14 Nov 2023 14:09:20 -0500 Subject: [PATCH 08/15] add loading spinner --- .../implementations/BipartiteNetworkVisualization.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index f6febe663e..3d444d720b 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -202,6 +202,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { const bipartiteNetworkProps: BipartiteNetworkProps = { data: cleanedData ?? undefined, + showSpinner: data.pending, }; const plotNode = ( From b6eea0531da3c01402e5665fe2baf95fc131c31a Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 14 Nov 2023 14:35:56 -0500 Subject: [PATCH 09/15] add styles to viz --- .../BipartiteNetworkVisualization.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 3d444d720b..435121564f 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -38,7 +38,6 @@ const DEFAULT_LINK_COLOR_DATA = '0'; const plotContainerStyles = { width: 750, - height: 450, marginLeft: '0.75rem', border: '1px solid #dedede', boxShadow: '1px 1px 4px #00000066', @@ -81,6 +80,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { computeJobStatus, filteredCounts, filters, + plotContainerStyleOverrides, } = props; const studyMetadata = useStudyMetadata(); @@ -194,15 +194,27 @@ function BipartiteNetworkViz(props: VisualizationProps) { options?.getPlotSubtitle?.(computation.descriptor.configuration) + DEFAULT_CORRELATION_COEF_THRESHOLD.toString(); + const finalPlotContainerStyles = useMemo( + () => ({ + ...plotContainerStyles, + ...plotContainerStyleOverrides, + }), + [plotContainerStyleOverrides] + ); + const plotRef = useUpdateThumbnailEffect( updateThumbnail, - plotContainerStyles, + { + ...finalPlotContainerStyles, + height: 400, // no reason for the thumbnail to be as tall as the network (could be very, very tall!) + }, [cleanedData] ); const bipartiteNetworkProps: BipartiteNetworkProps = { data: cleanedData ?? undefined, showSpinner: data.pending, + containerStyles: finalPlotContainerStyles, }; const plotNode = ( From 4d9564f7c5766e3c290fa0d15ad065efb1ecf89a Mon Sep 17 00:00:00 2001 From: asizemore Date: Tue, 14 Nov 2023 15:06:13 -0500 Subject: [PATCH 10/15] add empty-ish bpnet data --- .../libs/components/src/plots/BipartiteNetwork.tsx | 11 ++++++++--- .../src/stories/plots/BipartiteNetwork.stories.tsx | 10 +++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/libs/components/src/plots/BipartiteNetwork.tsx b/packages/libs/components/src/plots/BipartiteNetwork.tsx index f86844597e..4f81c8a4b2 100755 --- a/packages/libs/components/src/plots/BipartiteNetwork.tsx +++ b/packages/libs/components/src/plots/BipartiteNetwork.tsx @@ -14,6 +14,7 @@ import { DEFAULT_CONTAINER_HEIGHT } from './PlotlyPlot'; import Spinner from '../components/Spinner'; import { ToImgopts } from 'plotly.js'; import domToImage from 'dom-to-image'; +import { gray } from '@veupathdb/coreui/lib/definitions/colors'; export interface BipartiteNetworkProps { /** Bipartite network data */ @@ -33,9 +34,13 @@ export interface BipartiteNetworkProps { } const EmptyBipartiteNetworkData: BipartiteNetworkData = { - column1NodeIDs: [], - column2NodeIDs: [], - nodes: [], + column1NodeIDs: ['0', '1', '2', '3', '4', '5'], + column2NodeIDs: ['6', '7', '8'], + nodes: [...Array(9).keys()].map((item) => ({ + id: item.toString(), + color: gray[100], + stroke: gray[300], + })), links: [], }; diff --git a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx index bfc4d0ba8d..43e8d83ed9 100755 --- a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx +++ b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, CSSProperties } from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; import { NodeData, @@ -21,6 +21,7 @@ interface TemplateProps { column2Name?: string; loading?: boolean; showThumbnail?: boolean; + containerStyles?: CSSProperties; } // Template for showcasing our BipartiteNetwork component. @@ -42,6 +43,7 @@ const Template: Story = (args) => { column1Name: args.column1Name, column2Name: args.column2Name, showSpinner: args.loading, + containerStyles: args.containerStyles, width: 500, }; return ( @@ -93,6 +95,12 @@ Loading.args = { loading: true, }; +// Empty bipartite network +export const Empty = Template.bind({}); +Empty.args = { + data: undefined, +}; + // Show thumbnail export const Thumbnail = Template.bind({}); Thumbnail.args = { From a353a29de8c7101d6ad2c01e57e5001d282b91b7 Mon Sep 17 00:00:00 2001 From: asizemore Date: Wed, 15 Nov 2023 06:29:01 -0500 Subject: [PATCH 11/15] Add svg styling and handle overrides --- .../components/src/plots/BipartiteNetwork.tsx | 57 ++++++++++++------- .../plots/BipartiteNetwork.stories.tsx | 24 +++++++- .../BipartiteNetworkVisualization.tsx | 5 ++ 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/packages/libs/components/src/plots/BipartiteNetwork.tsx b/packages/libs/components/src/plots/BipartiteNetwork.tsx index 4f81c8a4b2..b191c5e034 100755 --- a/packages/libs/components/src/plots/BipartiteNetwork.tsx +++ b/packages/libs/components/src/plots/BipartiteNetwork.tsx @@ -16,6 +16,13 @@ import { ToImgopts } from 'plotly.js'; import domToImage from 'dom-to-image'; import { gray } from '@veupathdb/coreui/lib/definitions/colors'; +export interface BipartiteNetworkSVGStyles { + width?: number; // svg width + topPadding?: number; // space between the top of the svg and the top-most node + nodeSpacing?: number; // space between vertically adjacent nodes + columnPadding?: number; // space between the left of the svg and the left column, also the right of the svg and the right column. +} + export interface BipartiteNetworkProps { /** Bipartite network data */ data: BipartiteNetworkData | undefined; @@ -25,12 +32,14 @@ export interface BipartiteNetworkProps { column2Name?: string; /** styling for the plot's container */ containerStyles?: CSSProperties; + /** bipartite network-specific styling for the svg itself. These + * properties will override any adaptation the network may try to do based on the container styles. + */ + svgStyleOverrides?: BipartiteNetworkSVGStyles; /** container name */ containerClass?: string; /** shall we show the loading spinner? */ showSpinner?: boolean; - /** plot width */ - width?: number; } const EmptyBipartiteNetworkData: BipartiteNetworkData = { @@ -54,20 +63,12 @@ function BipartiteNetwork( data = EmptyBipartiteNetworkData, column1Name, column2Name, - containerStyles = { width: '100%', height: DEFAULT_CONTAINER_HEIGHT }, + containerStyles, + svgStyleOverrides, containerClass = 'web-components-plot', showSpinner = false, - width, } = props; - // Defaults - // Many of the below can get optional props in the future as we figure out optimal layouts - const DEFAULT_WIDTH = 400; - const DEFAULT_NODE_VERTICAL_SPACE = 30; - const DEFAULT_TOP_PADDING = 40; - const DEFAULT_COLUMN1_X = 100; - const DEFAULT_COLUMN2_X = (width ?? DEFAULT_WIDTH) - DEFAULT_COLUMN1_X; - // Use ref forwarding to enable screenshotting of the plot for thumbnail versions. const plotRef = useRef(null); useImperativeHandle( @@ -82,6 +83,18 @@ function BipartiteNetwork( [] ); + // Set up styles for the bipartite network and incorporate overrides + const svgStyles = { + width: Number(containerStyles?.width) || 400, + topPadding: 40, + nodeSpacing: 30, + columnPadding: 100, + ...svgStyleOverrides, + }; + + const column1Position = svgStyles.columnPadding; + const column2Position = svgStyles.width - svgStyles.columnPadding; + // In order to assign coordinates to each node, we'll separate the // nodes based on their column, then will use their order in the column // (given by columnXNodeIDs) to finally assign the coordinates. @@ -103,8 +116,8 @@ function BipartiteNetwork( return { // columnIndex of 0 refers to the left-column nodes whereas 1 refers to right-column nodes - x: columnIndex === 0 ? DEFAULT_COLUMN1_X : DEFAULT_COLUMN2_X, - y: DEFAULT_TOP_PADDING + DEFAULT_NODE_VERTICAL_SPACE * indexInColumn, + x: columnIndex === 0 ? column1Position : column2Position, + y: svgStyles.topPadding + svgStyles.nodeSpacing * indexInColumn, labelPosition: columnIndex === 0 ? 'left' : ('right' as LabelPosition), ...node, @@ -140,22 +153,22 @@ function BipartiteNetwork( return (
{/* Draw names of node colums if they exist */} {column1Name && ( {column1Name} @@ -163,8 +176,8 @@ function BipartiteNetwork( )} {column2Name && ( {column2Name} diff --git a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx index 43e8d83ed9..263973248e 100755 --- a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx +++ b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx @@ -7,6 +7,7 @@ import { } from '../../types/plots/network'; import BipartiteNetwork, { BipartiteNetworkProps, + BipartiteNetworkSVGStyles, } from '../../plots/BipartiteNetwork'; import { twoColorPalette } from '../../types/plots/addOns'; @@ -22,6 +23,7 @@ interface TemplateProps { loading?: boolean; showThumbnail?: boolean; containerStyles?: CSSProperties; + svgStyleOverrides?: BipartiteNetworkSVGStyles; } // Template for showcasing our BipartiteNetwork component. @@ -44,7 +46,7 @@ const Template: Story = (args) => { column2Name: args.column2Name, showSpinner: args.loading, containerStyles: args.containerStyles, - width: 500, + svgStyleOverrides: args.svgStyleOverrides, }; return ( <> @@ -110,6 +112,26 @@ Thumbnail.args = { showThumbnail: true, }; +// With style +const plotContainerStyles = { + width: 700, + marginLeft: '0.75rem', + border: '1px solid #dedede', + boxShadow: '1px 1px 4px #00000066', +}; +const svgStyleOverrides = { + columnPadding: 150, + topPadding: 100, +}; +export const WithStyle = Template.bind({}); +WithStyle.args = { + data: manyPointsData, + containerStyles: plotContainerStyles, + column1Name: 'Column 1', + column2Name: 'Column 2', + svgStyleOverrides: svgStyleOverrides, +}; + // Gerenate a bipartite network with a given number of nodes and random edges function genBipartiteNetwork( column1nNodes: number, diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 435121564f..168ac62834 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -202,6 +202,10 @@ function BipartiteNetworkViz(props: VisualizationProps) { [plotContainerStyleOverrides] ); + const bipartiteNetworkSVGStyles = { + columnPadding: 150, + }; + const plotRef = useUpdateThumbnailEffect( updateThumbnail, { @@ -215,6 +219,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { data: cleanedData ?? undefined, showSpinner: data.pending, containerStyles: finalPlotContainerStyles, + svgStyleOverrides: bipartiteNetworkSVGStyles, }; const plotNode = ( From a060b3f7e2e25b3289261801aac906ae4a22f2ae Mon Sep 17 00:00:00 2001 From: asizemore Date: Wed, 15 Nov 2023 06:47:52 -0500 Subject: [PATCH 12/15] clean and document --- .../libs/components/src/plots/BipartiteNetwork.tsx | 2 +- .../src/stories/plots/BipartiteNetwork.stories.tsx | 1 + .../plugins/correlationAssayMetadata.tsx | 4 ++-- .../BipartiteNetworkVisualization.tsx | 12 +++++++----- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/libs/components/src/plots/BipartiteNetwork.tsx b/packages/libs/components/src/plots/BipartiteNetwork.tsx index b191c5e034..79e696cd27 100755 --- a/packages/libs/components/src/plots/BipartiteNetwork.tsx +++ b/packages/libs/components/src/plots/BipartiteNetwork.tsx @@ -10,7 +10,6 @@ import { useImperativeHandle, useRef, } from 'react'; -import { DEFAULT_CONTAINER_HEIGHT } from './PlotlyPlot'; import Spinner from '../components/Spinner'; import { ToImgopts } from 'plotly.js'; import domToImage from 'dom-to-image'; @@ -42,6 +41,7 @@ export interface BipartiteNetworkProps { showSpinner?: boolean; } +// Show a few gray nodes when there is no real data. const EmptyBipartiteNetworkData: BipartiteNetworkData = { column1NodeIDs: ['0', '1', '2', '3', '4', '5'], column2NodeIDs: ['6', '7', '8'], diff --git a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx index 263973248e..15cceeb8a8 100755 --- a/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx +++ b/packages/libs/components/src/stories/plots/BipartiteNetwork.stories.tsx @@ -122,6 +122,7 @@ const plotContainerStyles = { const svgStyleOverrides = { columnPadding: 150, topPadding: 100, + // width: 300, // should override the plotContainerStyles.width }; export const WithStyle = Template.bind({}); WithStyle.args = { diff --git a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx index 7db5ded77d..19e4b4d5ca 100644 --- a/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx +++ b/packages/libs/eda/src/lib/core/components/computations/plugins/correlationAssayMetadata.tsx @@ -19,8 +19,8 @@ const cx = makeClassNameHelper('AppStepConfigurationContainer'); * Correlation * * The Correlation Assay vs Metadata app takes in a user-selected collection (ex. Species) and - * runs a correlation of that data against all appropriate metadata in the study. The result is - * a correlation coefficient and significance value for each (assay member, metadata variable) pair. + * runs a correlation of that data against all appropriate metadata in the study (found by the backend). The result is + * a correlation coefficient and (soon) a significance value for each (assay member, metadata variable) pair. * * Importantly, this is the first of a few correlation-type apps that are coming along in the near future. * There will also be an Assay vs Assay app and a Metadata vs Metadata correlation app. It's possible that diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 168ac62834..fa4f7a861b 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -132,7 +132,8 @@ function BipartiteNetworkViz(props: VisualizationProps) { // Assign color to links. // Color palettes live here in the frontend, but the backend decides how to color links (ex. by sign of correlation, or avg degree of parent nodes). - // So we'll make assigning colors generalizable by mapping the values of the links.color prop to the palette. + // So we'll make assigning colors generalizable by mapping the values of the links.color prop to the palette. As we add + // different ways to color links in the future, we can adapt our checks and error messaging. const uniqueLinkColors = uniq( data.value?.bipartitenetwork.data.links.map( (link) => link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA @@ -143,9 +144,9 @@ function BipartiteNetworkViz(props: VisualizationProps) { `Found ${uniqueLinkColors.length} link colors but expected only two.` ); } - // The link colors should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain - // this way prevents a situation where if all links have color '1', we don't want them mapped to the - // color that is usually reserved for '-1'. + // The link color sent from the backend should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain + // in the following way preserves "1" getting mapped to the second color in the palette, even if it's the only + // unique value in uniqueLinkColors. const linkColorScaleDomain = uniqueLinkColors.every((val) => ['-1', '1'].includes(val) ) @@ -202,6 +203,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { [plotContainerStyleOverrides] ); + // These styles affect the network plot and will override the containerStyles if necessary (for example, width). const bipartiteNetworkSVGStyles = { columnPadding: 150, }; @@ -210,7 +212,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { updateThumbnail, { ...finalPlotContainerStyles, - height: 400, // no reason for the thumbnail to be as tall as the network (could be very, very tall!) + height: 400, // no reason for the thumbnail to be as tall as the network (which could be very, very tall!) }, [cleanedData] ); From d4946843777573e93575a47b210c778486d7f77e Mon Sep 17 00:00:00 2001 From: Ann Sizemore Blevins Date: Thu, 16 Nov 2023 04:36:36 -0500 Subject: [PATCH 13/15] Update packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx Co-authored-by: Dave Falke --- .../implementations/BipartiteNetworkVisualization.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index fa4f7a861b..86ee9b8131 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -141,7 +141,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { ); if (uniqueLinkColors.length > twoColorPalette.length) { throw new Error( - `Found ${uniqueLinkColors.length} link colors but expected only two.` + `Found ${uniqueLinkColors.length} link colors but expected only {twoColorPalette.length}.` ); } // The link color sent from the backend should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain From bad85a357b024e01396ef5c5960d4da0a2a4eab3 Mon Sep 17 00:00:00 2001 From: asizemore Date: Fri, 17 Nov 2023 06:23:32 -0500 Subject: [PATCH 14/15] fix constant thumbnail generation --- .../BipartiteNetworkVisualization.tsx | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx index 86ee9b8131..c57cafce69 100755 --- a/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx +++ b/packages/libs/eda/src/lib/core/components/visualizations/implementations/BipartiteNetworkVisualization.tsx @@ -130,36 +130,36 @@ function BipartiteNetworkViz(props: VisualizationProps) { ]) ); - // Assign color to links. - // Color palettes live here in the frontend, but the backend decides how to color links (ex. by sign of correlation, or avg degree of parent nodes). - // So we'll make assigning colors generalizable by mapping the values of the links.color prop to the palette. As we add - // different ways to color links in the future, we can adapt our checks and error messaging. - const uniqueLinkColors = uniq( - data.value?.bipartitenetwork.data.links.map( - (link) => link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA - ) - ); - if (uniqueLinkColors.length > twoColorPalette.length) { - throw new Error( - `Found ${uniqueLinkColors.length} link colors but expected only {twoColorPalette.length}.` - ); - } - // The link color sent from the backend should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain - // in the following way preserves "1" getting mapped to the second color in the palette, even if it's the only - // unique value in uniqueLinkColors. - const linkColorScaleDomain = uniqueLinkColors.every((val) => - ['-1', '1'].includes(val) - ) - ? ['-1', '1'] - : uniqueLinkColors; - const linkColorScale = scaleOrdinal() - .domain(linkColorScaleDomain) - .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts (ex. not a correlation app). - // Clean and finalize data format. Specifically, assign link colors, add display labels const cleanedData = useMemo(() => { if (!data.value) return undefined; + // Assign color to links. + // Color palettes live here in the frontend, but the backend decides how to color links (ex. by sign of correlation, or avg degree of parent nodes). + // So we'll make assigning colors generalizable by mapping the values of the links.color prop to the palette. As we add + // different ways to color links in the future, we can adapt our checks and error messaging. + const uniqueLinkColors = uniq( + data.value?.bipartitenetwork.data.links.map( + (link) => link.color?.toString() ?? DEFAULT_LINK_COLOR_DATA + ) + ); + if (uniqueLinkColors.length > twoColorPalette.length) { + throw new Error( + `Found ${uniqueLinkColors.length} link colors but expected only two.` + ); + } + // The link color sent from the backend should be either '-1' or '1', but we'll allow any two unique values. Assigning the domain + // in the following way preserves "1" getting mapped to the second color in the palette, even if it's the only + // unique value in uniqueLinkColors. + const linkColorScaleDomain = uniqueLinkColors.every((val) => + ['-1', '1'].includes(val) + ) + ? ['-1', '1'] + : uniqueLinkColors; + const linkColorScale = scaleOrdinal() + .domain(linkColorScaleDomain) + .range(twoColorPalette); // the output palette may change if this visualization is reused in other contexts (ex. not a correlation app). + // Find display labels const nodesWithLabels = data.value.bipartitenetwork.data.nodes.map( (node) => { @@ -188,7 +188,7 @@ function BipartiteNetworkViz(props: VisualizationProps) { }; }), }; - }, [data, entities, linkColorScale]); + }, [data.value, entities]); // plot subtitle const plotSubtitle = From f8944a97eb753cc13609b35be52d351cc2b09af9 Mon Sep 17 00:00:00 2001 From: asizemore Date: Fri, 17 Nov 2023 06:31:35 -0500 Subject: [PATCH 15/15] increase weight of bpnet text --- packages/libs/components/src/plots/BipartiteNetwork.css | 4 ++++ packages/libs/components/src/plots/BipartiteNetwork.tsx | 3 +++ packages/libs/components/src/plots/Network.tsx | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 packages/libs/components/src/plots/BipartiteNetwork.css diff --git a/packages/libs/components/src/plots/BipartiteNetwork.css b/packages/libs/components/src/plots/BipartiteNetwork.css new file mode 100644 index 0000000000..87d91b4ea4 --- /dev/null +++ b/packages/libs/components/src/plots/BipartiteNetwork.css @@ -0,0 +1,4 @@ +.BipartiteNetworkColumnTitle { + font-size: 1em; + font-weight: 500; +} diff --git a/packages/libs/components/src/plots/BipartiteNetwork.tsx b/packages/libs/components/src/plots/BipartiteNetwork.tsx index 79e696cd27..23199641cf 100755 --- a/packages/libs/components/src/plots/BipartiteNetwork.tsx +++ b/packages/libs/components/src/plots/BipartiteNetwork.tsx @@ -14,6 +14,7 @@ import Spinner from '../components/Spinner'; import { ToImgopts } from 'plotly.js'; import domToImage from 'dom-to-image'; import { gray } from '@veupathdb/coreui/lib/definitions/colors'; +import './BipartiteNetwork.css'; export interface BipartiteNetworkSVGStyles { width?: number; // svg width @@ -170,6 +171,7 @@ function BipartiteNetwork( x={column1Position} y={svgStyles.topPadding / 2} textAnchor="end" + className="BipartiteNetworkColumnTitle" > {column1Name} @@ -179,6 +181,7 @@ function BipartiteNetwork( x={column2Position} y={svgStyles.topPadding / 2} textAnchor="start" + className="BipartiteNetworkColumnTitle" > {column2Name} diff --git a/packages/libs/components/src/plots/Network.tsx b/packages/libs/components/src/plots/Network.tsx index 66243bb1cf..2ac3127b8e 100755 --- a/packages/libs/components/src/plots/Network.tsx +++ b/packages/libs/components/src/plots/Network.tsx @@ -32,7 +32,7 @@ export function NodeWithLabel(props: NodeWithLabelProps) { onClick, labelPosition = 'right', fontSize = '1em', - fontWeight = 200, + fontWeight = 400, labelColor = '#000', } = props;