Skip to content

Commit

Permalink
Add self-correlation app and network visualization (#1090)
Browse files Browse the repository at this point in the history
* add self-correlations plugin

* succesful network response

* cleanup and address funny sizing issues

* restrict selfcorrelation to taxa

* fix empty network alignment

* cleanup

* Update packages/libs/eda/src/lib/core/components/computations/plugins/selfCorrelation.tsx

Co-authored-by: Dave Falke <[email protected]>

* comment, clean types, remove unnecessary memo

---------

Co-authored-by: Dave Falke <[email protected]>
  • Loading branch information
asizemore and dmfalke authored Jun 28, 2024
1 parent ab9565e commit 8493062
Show file tree
Hide file tree
Showing 9 changed files with 885 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/libs/components/src/plots/NetworkPlot.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

.network-plot-container {
width: 100%;
height: 500px;
overflow-y: scroll;
height: 800px;
/* overflow-y: scroll; */
}

.net-hover-dropdown {
Expand Down
10 changes: 5 additions & 5 deletions packages/libs/components/src/plots/NetworkPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ export interface NetworkPlotProps {
annotations?: ReactNode[];
}

const DEFAULT_PLOT_WIDTH = 500;
const DEFAULT_PLOT_HEIGHT = 500;
const DEFAULT_PLOT_WIDTH = 800;
const DEFAULT_PLOT_HEIGHT = 900;

const emptyNodes: NodeData[] = [...Array(9).keys()].map((item, index) => ({
id: item.toString(),
color: gray[100],
stroke: gray[300],
x: 230 + 200 * Math.cos(2 * Math.PI * (index / 9)),
y: 230 + 200 * Math.sin(2 * Math.PI * (index / 9)),
x: 400 + 200 * Math.cos(2 * Math.PI * (index / 9)),
y: 300 + 200 * Math.sin(2 * Math.PI * (index / 9)),
}));
const emptyLinks: LinkData[] = [];

Expand All @@ -73,7 +73,7 @@ function NetworkPlot(props: NetworkPlotProps, ref: Ref<HTMLDivElement>) {
svgStyleOverrides,
containerClass = 'web-components-plot',
showSpinner = false,
labelTruncationLength = 20,
labelTruncationLength = 10,
emptyNetworkContent,
annotations,
} = props;
Expand Down
2 changes: 2 additions & 0 deletions packages/libs/components/src/types/plots/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export type LinkData = {
color?: string;
/** Link opacity. Must be between 0 and 1 */
opacity?: number;
/** Boolean determining if the edge is directed */
isDirected?: boolean;
};

/** NetworkData is the same format accepted by visx's Graph component. */
Expand Down
64 changes: 60 additions & 4 deletions packages/libs/eda/src/lib/core/api/DataClient/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
keyof,
boolean,
literal,
any,
} from 'io-ts';
import { Filter } from '../../types/filter';
import {
Expand Down Expand Up @@ -391,13 +392,64 @@ export const NodeIdList = type({
nodeIds: array(string),
});

// Bipartite network
export type BipartiteNetworkResponse = TypeOf<typeof BipartiteNetworkResponse>;
// Network types (including bipartite network)
// The network types are all built from nodes and links. Currently we've defined specific
// flavors of networks, called "correlation" networks, that have extra information
// about them based on their context.

// NOTE tech debt below! The `sourece` and `target` of the NetworkData links should be
// NodeData, but the backend is sending us strings. At this point it is unlikely the backend
// will change for a while to fix this issue. If it does, we can simplify the below and let
// BipartiteNetworkData extend NetworkData.
const NodeData = intersection([
type({
id: string,
}),
partial({
x: number,
y: number,
degree: number,
}),
]);

const NodeData = type({
id: string,
export const NetworkData = type({
nodes: array(NodeData),
links: array(
intersection([
type({
source: string,
target: string,
weight: number,
}),
partial({
color: number,
isDirected: boolean,
}),
])
),
});

const NetworkConfig = partial({
variables: unknown,
correlationCoefThreshold: number,
significanceThreshold: number,
});
export const NetworkResponse = type({
network: type({
data: NetworkData,
config: NetworkConfig,
}),
});

export interface NetworkRequestParams {
studyId: string;
filters: Filter[];
config: {
correlationCoefThreshold?: number;
significanceThreshold?: number;
};
}

export const BipartiteNetworkData = type({
partitions: array(NodeIdList),
nodes: array(NodeData),
Expand Down Expand Up @@ -426,6 +478,8 @@ export const BipartiteNetworkResponse = type({
}),
});

export type BipartiteNetworkResponse = TypeOf<typeof BipartiteNetworkResponse>;

// Correlation Bipartite Network
// a specific flavor of the bipartite network that also includes correlationCoefThreshold and significanceThreshold
export type CorrelationBipartiteNetworkResponse = TypeOf<
Expand All @@ -448,6 +502,8 @@ export interface BipartiteNetworkRequestParams {
};
}

export type NetworkResponse = TypeOf<typeof NetworkResponse>;

export type FeaturePrefilterThresholds = TypeOf<
typeof FeaturePrefilterThresholds
>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export function isTaxonomicVariableCollection(
return (
isNotAbsoluteAbundanceVariableCollection(variableCollection) &&
(variableCollection.member
? variableCollection.member === 'taxon'
? variableCollection.member === 'taxon' &&
!!variableCollection.isCompositional
: variableCollection.normalizationMethod === 'sumToUnity') // if we have a member annotation, use that. Old datasets may not have this annotation, hence the fall back normalizationMethod check.
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { plugin as differentialabundance } from './differentialabundance';
import { plugin as correlationassaymetadata } from './correlationAssayMetadata'; // mbio
import { plugin as correlationassayassay } from './correlationAssayAssay'; // mbio
import { plugin as correlation } from './correlation'; // genomics (- vb)
import { plugin as selfcorrelation } from './selfCorrelation';
import { plugin as xyrelationships } from './xyRelationships';
export const plugins: Record<string, ComputationPlugin> = {
abundance,
Expand All @@ -18,6 +19,7 @@ export const plugins: Record<string, ComputationPlugin> = {
correlationassaymetadata,
correlationassayassay,
correlation,
selfcorrelation,
countsandproportions,
distributions,
pass,
Expand Down
Loading

0 comments on commit 8493062

Please sign in to comment.